Move all files to 2017/
This commit is contained in:
parent
ac7370f67f
commit
2875863330
15717 changed files with 0 additions and 0 deletions
Binary file not shown.
59
2017/web/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8201.php
vendored
Normal file
59
2017/web/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8201.php
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
|
||||
* upgrade path of rest_update_8201().
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Set the schema version.
|
||||
$connection->insert('key_value')
|
||||
->fields([
|
||||
'collection' => 'system.schema',
|
||||
'name' => 'rest',
|
||||
'value' => 'i:8000;',
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Update core.extension.
|
||||
$extensions = $connection->select('config')
|
||||
->fields('config', ['data'])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$extensions = unserialize($extensions);
|
||||
$extensions['module']['basic_auth'] = 0;
|
||||
$extensions['module']['rest'] = 0;
|
||||
$extensions['module']['serialization'] = 0;
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($extensions),
|
||||
])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute();
|
||||
|
||||
// Install the rest configuration.
|
||||
$config = [
|
||||
'resources' => [
|
||||
'entity:node' => [
|
||||
'GET' => [
|
||||
'supported_formats' => ['json'],
|
||||
'supported_auth' => ['basic_auth'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'link_domain' => NULL,
|
||||
];
|
||||
$data = $connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'rest.settings',
|
||||
'data' => serialize($config),
|
||||
'collection' => '',
|
||||
])
|
||||
->execute();
|
||||
58
2017/web/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8203.php
vendored
Normal file
58
2017/web/core/modules/rest/tests/fixtures/update/drupal-8.rest-rest_update_8203.php
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
|
||||
* upgrade path of rest_update_8203().
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Set the schema version.
|
||||
$connection->insert('key_value')
|
||||
->fields([
|
||||
'collection' => 'system.schema',
|
||||
'name' => 'rest',
|
||||
'value' => 'i:8000;',
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Update core.extension.
|
||||
$extensions = $connection->select('config')
|
||||
->fields('config', ['data'])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$extensions = unserialize($extensions);
|
||||
$extensions['module']['rest'] = 0;
|
||||
$extensions['module']['serialization'] = 0;
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($extensions),
|
||||
])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute();
|
||||
|
||||
// Install the rest configuration.
|
||||
$config = [
|
||||
'resources' => [
|
||||
'entity:node' => [
|
||||
'GET' => [
|
||||
'supported_formats' => ['json'],
|
||||
'supported_auth' => ['basic_auth'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'link_domain' => NULL,
|
||||
];
|
||||
$data = $connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'rest.settings',
|
||||
'data' => serialize($config),
|
||||
'collection' => '',
|
||||
])
|
||||
->execute();
|
||||
63
2017/web/core/modules/rest/tests/fixtures/update/rest-export-with-authentication-correction.php
vendored
Normal file
63
2017/web/core/modules/rest/tests/fixtures/update/rest-export-with-authentication-correction.php
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test fixture for \Drupal\Tests\rest\Functional\Update\RestExportAuthCorrectionUpdateTest.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
|
||||
// Set the schema version.
|
||||
$connection->insert('key_value')
|
||||
->fields([
|
||||
'collection' => 'system.schema',
|
||||
'name' => 'rest',
|
||||
'value' => 'i:8000;',
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Update core.extension.
|
||||
$extensions = $connection->select('config')
|
||||
->fields('config', ['data'])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$extensions = unserialize($extensions);
|
||||
$extensions['module']['rest'] = 0;
|
||||
$extensions['module']['serialization'] = 0;
|
||||
$extensions['module']['basic_auth'] = 0;
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($extensions),
|
||||
])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'rest.settings',
|
||||
'data' => serialize([
|
||||
'link_domain' => '~',
|
||||
]),
|
||||
'collection' => '',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'views.view.rest_export_with_authorization_correction',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->merge('config')
|
||||
->condition('name', 'views.view.rest_export_with_authorization_correction')
|
||||
->condition('collection', '')
|
||||
->fields([
|
||||
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/modules/views_test_config/test_views/views.view.rest_export_with_authorization_correction.yml'))),
|
||||
])
|
||||
->execute();
|
||||
65
2017/web/core/modules/rest/tests/fixtures/update/rest-export-with-authentication.php
vendored
Normal file
65
2017/web/core/modules/rest/tests/fixtures/update/rest-export-with-authentication.php
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test fixture for \Drupal\rest\Tests\Update\RestExportAuthUpdateTest.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Drupal\Core\Serialization\Yaml;
|
||||
|
||||
$connection = Database::getConnection();
|
||||
$config = $connection;
|
||||
|
||||
// Set the schema version.
|
||||
$connection->insert('key_value')
|
||||
->fields([
|
||||
'collection' => 'system.schema',
|
||||
'name' => 'rest',
|
||||
'value' => 'i:8000;',
|
||||
])
|
||||
->execute();
|
||||
|
||||
// Update core.extension.
|
||||
$extensions = $connection->select('config')
|
||||
->fields('config', ['data'])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$extensions = unserialize($extensions);
|
||||
$extensions['module']['rest'] = 0;
|
||||
$extensions['module']['serialization'] = 0;
|
||||
$extensions['module']['basic_auth'] = 0;
|
||||
$connection->update('config')
|
||||
->fields([
|
||||
'data' => serialize($extensions),
|
||||
])
|
||||
->condition('collection', '')
|
||||
->condition('name', 'core.extension')
|
||||
->execute();
|
||||
|
||||
$config = [
|
||||
'link_domain' => '~',
|
||||
];
|
||||
$data = $connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'rest.settings',
|
||||
'data' => serialize($config),
|
||||
'collection' => '',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->insert('config')
|
||||
->fields([
|
||||
'name' => 'views.view.rest_export_with_authorization',
|
||||
])
|
||||
->execute();
|
||||
|
||||
$connection->merge('config')
|
||||
->condition('name', 'views.view.rest_export_with_authorization')
|
||||
->condition('collection', '')
|
||||
->fields([
|
||||
'data' => serialize(Yaml::decode(file_get_contents('core/modules/views/tests/modules/views_test_config/test_views/views.view.rest_export_with_authorization.yml'))),
|
||||
])
|
||||
->execute();
|
||||
32
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
vendored
Normal file
32
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.comment_2721595.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
id: entity.comment
|
||||
plugin_id: 'entity:comment'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
# This resource has a method-specific format.
|
||||
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
|
||||
- xml
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
||||
29
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
vendored
Normal file
29
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.node_2721595.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
id: entity.node
|
||||
plugin_id: 'entity:node'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
||||
32
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
vendored
Normal file
32
2017/web/core/modules/rest/tests/fixtures/update/rest.resource.entity.user_2721595.yml
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
id: entity.user
|
||||
plugin_id: 'entity:user'
|
||||
granularity: method
|
||||
configuration:
|
||||
GET:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
# This resource has a method-specific authentication.
|
||||
# @see \Drupal\rest\Tests\Update\ResourceGranularityUpdateTest
|
||||
- oauth
|
||||
POST:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
PATCH:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
DELETE:
|
||||
supported_formats:
|
||||
- hal_json
|
||||
supported_auth:
|
||||
- basic_auth
|
||||
dependencies:
|
||||
module:
|
||||
- node
|
||||
- basic_auth
|
||||
- hal
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
name: 'Configuration test REST'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:config_test
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains hook implementations for testing REST module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_type_alter().
|
||||
*/
|
||||
function config_test_rest_entity_type_alter(array &$entity_types) {
|
||||
// Undo part of what config_test_entity_type_alter() did: remove this
|
||||
// config_test_no_status entity type, because it uses the same entity class as
|
||||
// the config_test entity type, which makes REST deserialization impossible.
|
||||
unset($entity_types['config_test_no_status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ENTITY_TYPE_access().
|
||||
*/
|
||||
function config_test_rest_config_test_access(EntityInterface $entity, $operation, AccountInterface $account) {
|
||||
// Add permission, so that EntityResourceTestBase's scenarios can test access
|
||||
// being denied. By default, all access is always allowed for the config_test
|
||||
// config entity.
|
||||
return AccessResult::forbiddenIf(!$account->hasPermission('view config_test'))->cachePerPermissions();
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
view config_test:
|
||||
title: 'View ConfigTest entities'
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
name: 'REST test'
|
||||
type: module
|
||||
description: 'Provides test hooks and resources for REST module.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains hook implementations for testing REST module.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_field_access().
|
||||
*
|
||||
* @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::setUp()
|
||||
*/
|
||||
function rest_test_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testPost()
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testPatch()
|
||||
if ($field_definition->getName() === 'field_rest_test') {
|
||||
switch ($operation) {
|
||||
case 'view':
|
||||
// Never ever allow this field to be viewed: this lets
|
||||
// EntityResourceTestBase::testGet() test in a "vanilla" way.
|
||||
return AccessResult::forbidden();
|
||||
case 'edit':
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testGet()
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testPatch()
|
||||
if ($field_definition->getName() === 'field_rest_test_multivalue') {
|
||||
switch ($operation) {
|
||||
case 'view':
|
||||
// Never ever allow this field to be viewed: this lets
|
||||
// EntityResourceTestBase::testGet() test in a "vanilla" way.
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testGet()
|
||||
// @see \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testPatch()
|
||||
if ($field_definition->getName() === 'rest_test_validation') {
|
||||
switch ($operation) {
|
||||
case 'view':
|
||||
// Never ever allow this field to be viewed: this lets
|
||||
// EntityResourceTestBase::testGet() test in a "vanilla" way.
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
// No opinion.
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info().
|
||||
*/
|
||||
function rest_test_entity_base_field_info(EntityTypeInterface $entity_type) {
|
||||
$fields = [];
|
||||
$fields['rest_test_validation'] = BaseFieldDefinition::create('string')
|
||||
->setLabel(t('REST test validation field'))
|
||||
->setDescription(t('A text field with some special validations attached used for testing purposes'))
|
||||
->addConstraint('rest_test_validation');
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
services:
|
||||
rest_test.authentication.test_auth:
|
||||
class: Drupal\rest_test\Authentication\Provider\TestAuth
|
||||
tags:
|
||||
- { name: authentication_provider, provider_id: 'rest_test_auth' }
|
||||
rest_test.authentication.test_auth_global:
|
||||
class: Drupal\rest_test\Authentication\Provider\TestAuthGlobal
|
||||
tags:
|
||||
- { name: authentication_provider, provider_id: 'rest_test_auth_global', global: TRUE }
|
||||
rest_test.page_cache_request_policy.deny_test_auth_requests:
|
||||
class: Drupal\rest_test\PageCache\RequestPolicy\DenyTestAuthRequests
|
||||
public: false
|
||||
tags:
|
||||
- { name: page_cache_request_policy }
|
||||
rest_test.encoder.foobar:
|
||||
class: Drupal\serialization\Encoder\JsonEncoder
|
||||
tags:
|
||||
- { name: encoder, format: foobar }
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\Authentication\Provider;
|
||||
|
||||
use Drupal\Core\Authentication\AuthenticationProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Authentication provider for testing purposes.
|
||||
*/
|
||||
class TestAuth implements AuthenticationProviderInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies(Request $request) {
|
||||
return $request->headers->has('REST-test-auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate(Request $request) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\Authentication\Provider;
|
||||
|
||||
use Drupal\Core\Authentication\AuthenticationProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Global authentication provider for testing purposes.
|
||||
*/
|
||||
class TestAuthGlobal implements AuthenticationProviderInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies(Request $request) {
|
||||
return $request->headers->has('REST-test-auth-global');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate(Request $request) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\PageCache\RequestPolicy;
|
||||
|
||||
use Drupal\Core\PageCache\RequestPolicyInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Cache policy for pages requested with REST Test Auth.
|
||||
*
|
||||
* This policy disallows caching of requests that use the REST Test Auth
|
||||
* authentication provider for security reasons (just like basic_auth).
|
||||
* Otherwise responses for authenticated requests can get into the page cache
|
||||
* and could be delivered to unprivileged users.
|
||||
*
|
||||
* @see \Drupal\rest_test\Authentication\Provider\TestAuth
|
||||
* @see \Drupal\rest_test\Authentication\Provider\TestAuthGlobal
|
||||
* @see \Drupal\basic_auth\PageCache\DisallowBasicAuthRequests
|
||||
*/
|
||||
class DenyTestAuthRequests implements RequestPolicyInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function check(Request $request) {
|
||||
if ($request->headers->has('REST-test-auth') || $request->headers->has('REST-test-auth-global')) {
|
||||
return self::DENY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Adds some validations for a REST test field.
|
||||
*
|
||||
* @Constraint(
|
||||
* id = "rest_test_validation",
|
||||
* label = @Translation("REST test validation", context = "Validation")
|
||||
* )
|
||||
*
|
||||
* @see \Drupal\Core\TypedData\OptionsProviderInterface
|
||||
*/
|
||||
class RestTestConstraint extends Constraint {
|
||||
|
||||
public $message = 'REST test validation failed';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\Plugin\Validation\Constraint;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Validator for \Drupal\rest_test\Plugin\Validation\Constraint\RestTestConstraint.
|
||||
*/
|
||||
class RestTestConstraintValidator extends ConstraintValidator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($value, Constraint $constraint) {
|
||||
if ($value instanceof FieldItemListInterface) {
|
||||
$value = $value->getValue();
|
||||
if (!empty($value[0]['value']) && $value[0]['value'] === 'ALWAYS_FAIL') {
|
||||
$this->context->addViolation($constraint->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\rest_test\Plugin\rest\resource;
|
||||
|
||||
use Drupal\rest\Plugin\ResourceBase;
|
||||
use Drupal\rest\ResourceResponse;
|
||||
|
||||
/**
|
||||
* Class used to test that serialization_class is optional.
|
||||
*
|
||||
* @RestResource(
|
||||
* id = "serialization_test",
|
||||
* label = @Translation("Optional serialization_class"),
|
||||
* serialization_class = "",
|
||||
* uri_paths = {}
|
||||
* )
|
||||
*/
|
||||
class NoSerializationClassTestResource extends ResourceBase {
|
||||
|
||||
/**
|
||||
* Responds to a POST request.
|
||||
*
|
||||
* @param array $data
|
||||
* An array with the payload.
|
||||
*
|
||||
* @return \Drupal\rest\ResourceResponse
|
||||
*/
|
||||
public function post(array $data) {
|
||||
return new ResourceResponse($data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
name: 'REST test views'
|
||||
type: module
|
||||
description: 'Provides default views for views REST tests.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- drupal:rest
|
||||
- drupal:views
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Test hook implementations for the REST views test module.
|
||||
*/
|
||||
|
||||
use Drupal\views\ViewExecutable;
|
||||
|
||||
/**
|
||||
* Implements hook_views_post_execute().
|
||||
*/
|
||||
function rest_test_views_views_post_execute(ViewExecutable $view) {
|
||||
// Attach a custom header to the test_data_export view.
|
||||
if ($view->id() === 'test_serializer_display_entity') {
|
||||
if ($value = \Drupal::state()->get('rest_test_views_set_header', FALSE)) {
|
||||
$view->getResponse()->headers->set('Custom-Header', $value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- node.type.article
|
||||
module:
|
||||
- node
|
||||
- rest
|
||||
- user
|
||||
id: test_excluded_field_token_display
|
||||
label: 'Test Excluded Field Token Display'
|
||||
module: views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: 0
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
options: { }
|
||||
query:
|
||||
type: views_query
|
||||
options:
|
||||
disable_sql_rewrite: false
|
||||
distinct: false
|
||||
replica: false
|
||||
query_comment: ''
|
||||
query_tags: { }
|
||||
exposed_form:
|
||||
type: basic
|
||||
options:
|
||||
submit_button: Apply
|
||||
reset_button: false
|
||||
reset_button_label: Reset
|
||||
exposed_sorts_label: 'Sort by'
|
||||
expose_sort_order: true
|
||||
sort_asc_label: Asc
|
||||
sort_desc_label: Desc
|
||||
pager:
|
||||
type: mini
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
id: 0
|
||||
total_pages: null
|
||||
expose:
|
||||
items_per_page: false
|
||||
items_per_page_label: 'Items per page'
|
||||
items_per_page_options: '5, 10, 25, 50'
|
||||
items_per_page_options_all: false
|
||||
items_per_page_options_all_label: '- All -'
|
||||
offset: false
|
||||
offset_label: Offset
|
||||
tags:
|
||||
previous: ‹‹
|
||||
next: ››
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: fields
|
||||
options:
|
||||
inline: { }
|
||||
separator: ''
|
||||
hide_empty: false
|
||||
default_field_elements: true
|
||||
fields:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: true
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: false
|
||||
ellipsis: false
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: false
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
plugin_id: field
|
||||
nothing:
|
||||
id: nothing
|
||||
table: views
|
||||
field: nothing
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: ''
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: true
|
||||
text: '{{ title }}'
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: false
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: false
|
||||
plugin_id: custom
|
||||
filters:
|
||||
status:
|
||||
value: '1'
|
||||
table: node_field_data
|
||||
field: status
|
||||
plugin_id: boolean
|
||||
entity_type: node
|
||||
entity_field: status
|
||||
id: status
|
||||
expose:
|
||||
operator: ''
|
||||
group: 1
|
||||
type:
|
||||
id: type
|
||||
table: node_field_data
|
||||
field: type
|
||||
value:
|
||||
article: article
|
||||
entity_type: node
|
||||
entity_field: type
|
||||
plugin_id: bundle
|
||||
sorts:
|
||||
nid:
|
||||
id: nid
|
||||
table: node_field_data
|
||||
field: nid
|
||||
order: DESC
|
||||
entity_type: node
|
||||
entity_field: nid
|
||||
plugin_id: standard
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
exposed: false
|
||||
expose:
|
||||
label: ''
|
||||
header: { }
|
||||
footer: { }
|
||||
empty: { }
|
||||
relationships: { }
|
||||
arguments: { }
|
||||
display_extenders: { }
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- request_format
|
||||
- url.query_args
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: 'REST export'
|
||||
position: 1
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
path: rest/test/excluded-field-token
|
||||
pager:
|
||||
type: some
|
||||
options:
|
||||
items_per_page: 10
|
||||
offset: 0
|
||||
style:
|
||||
type: serializer
|
||||
options:
|
||||
formats:
|
||||
json: json
|
||||
row:
|
||||
type: data_field
|
||||
options:
|
||||
field_options:
|
||||
title:
|
||||
alias: ''
|
||||
raw_output: false
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- request_format
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags: { }
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- rest
|
||||
- user
|
||||
id: test_serializer_display_entity
|
||||
label: 'Test serialize display entity rows'
|
||||
module: rest
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: entity_test
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_entity
|
||||
sorts:
|
||||
id:
|
||||
id: standard
|
||||
table: entity_test
|
||||
field: id
|
||||
order: DESC
|
||||
plugin_id: date
|
||||
entity_type: entity_test
|
||||
entity_field: id
|
||||
title: 'Test serialize'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
path: test/serialize/entity
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- entity_test
|
||||
- rest
|
||||
id: test_serializer_display_entity_translated
|
||||
label: 'Test serialize translated entity rows'
|
||||
module: rest
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: entity_test_mul_property_data
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_entity
|
||||
title: 'Test serialize translated entity rows'
|
||||
rendering_language: '***LANGUAGE_entity_translation***'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
path: test/serialize/translated_entity
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- rest
|
||||
- user
|
||||
id: test_serializer_display_field
|
||||
label: 'Test serializer display field rows'
|
||||
module: rest
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: views_test_data
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
fields:
|
||||
name:
|
||||
id: name
|
||||
table: views_test_data
|
||||
field: name
|
||||
label: ''
|
||||
plugin_id: string
|
||||
nothing:
|
||||
id: nothing
|
||||
table: views
|
||||
field: nothing
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: 'Custom text'
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: true
|
||||
text: TEST
|
||||
plugin_id: custom
|
||||
created:
|
||||
id: created
|
||||
table: views_test_data
|
||||
field: created
|
||||
type: timestamp
|
||||
settings:
|
||||
date_format: medium
|
||||
custom_date_format: ''
|
||||
timezone: ''
|
||||
plugin_id: field
|
||||
sorts:
|
||||
created:
|
||||
id: created
|
||||
table: views_test_data
|
||||
field: created
|
||||
order: DESC
|
||||
plugin_id: date
|
||||
title: 'Test serialize'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
style: false
|
||||
row: false
|
||||
path: test/serialize/field
|
||||
access:
|
||||
type: none
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
rest_export_2:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_2
|
||||
display_title: 'serialize - access denied'
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
style: false
|
||||
row: false
|
||||
path: test/serialize/denied
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'administer views'
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.body
|
||||
module:
|
||||
- field
|
||||
- node
|
||||
- rest
|
||||
- rest_test_views
|
||||
- user
|
||||
id: test_serializer_node_display_field
|
||||
label: 'Test serializer display field rows for entity fields'
|
||||
module: rest_test_views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'administer views'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
fields:
|
||||
nid:
|
||||
id: nid
|
||||
table: node_field_data
|
||||
field: nid
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: nid
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
label: Title
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
element_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
type: string
|
||||
settings:
|
||||
link_to_entity: true
|
||||
plugin_id: field
|
||||
body:
|
||||
id: body
|
||||
table: node__body
|
||||
field: body
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Body
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: text_default
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: body
|
||||
title: 'Test serialize'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
style: false
|
||||
row: false
|
||||
path: test/serialize/node-field
|
||||
access:
|
||||
type: none
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
|
||||
rest_export_2:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_2
|
||||
display_title: 'REST export 2'
|
||||
position: 2
|
||||
display_options:
|
||||
display_extenders: { }
|
||||
auth:
|
||||
basic_auth: basic_auth
|
||||
path: test/serialize/auth_with_perm
|
||||
cache_metadata:
|
||||
max-age: -1
|
||||
contexts:
|
||||
- 'languages:language_content'
|
||||
- 'languages:language_interface'
|
||||
- request_format
|
||||
- 'user.node_grants:view'
|
||||
- user.permissions
|
||||
tags:
|
||||
- 'config:field.storage.node.body'
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
config:
|
||||
- field.storage.node.body
|
||||
module:
|
||||
- field
|
||||
- node
|
||||
- rest
|
||||
- rest_test_views
|
||||
- user
|
||||
id: test_serializer_node_exposed_filter
|
||||
label: 'Test serializer display for exposed filters'
|
||||
module: rest_test_views
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: node_field_data
|
||||
base_field: nid
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
fields:
|
||||
nid:
|
||||
id: nid
|
||||
table: node_field_data
|
||||
field: nid
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: nid
|
||||
body:
|
||||
id: body
|
||||
table: node__body
|
||||
field: body
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
label: Body
|
||||
exclude: false
|
||||
alter:
|
||||
alter_text: false
|
||||
text: ''
|
||||
make_link: false
|
||||
path: ''
|
||||
absolute: false
|
||||
external: false
|
||||
replace_spaces: false
|
||||
path_case: none
|
||||
trim_whitespace: false
|
||||
alt: ''
|
||||
rel: ''
|
||||
link_class: ''
|
||||
prefix: ''
|
||||
suffix: ''
|
||||
target: ''
|
||||
nl2br: false
|
||||
max_length: 0
|
||||
word_boundary: true
|
||||
ellipsis: true
|
||||
more_link: false
|
||||
more_link_text: ''
|
||||
more_link_path: ''
|
||||
strip_tags: false
|
||||
trim: false
|
||||
preserve_tags: ''
|
||||
html: false
|
||||
element_type: ''
|
||||
element_class: ''
|
||||
element_label_type: ''
|
||||
element_label_class: ''
|
||||
element_label_colon: true
|
||||
element_wrapper_type: ''
|
||||
element_wrapper_class: ''
|
||||
element_default_classes: true
|
||||
empty: ''
|
||||
hide_empty: false
|
||||
empty_zero: false
|
||||
hide_alter_empty: true
|
||||
click_sort_column: value
|
||||
type: text_default
|
||||
settings: { }
|
||||
group_column: value
|
||||
group_columns: { }
|
||||
group_rows: true
|
||||
delta_limit: 0
|
||||
delta_offset: 0
|
||||
delta_reversed: false
|
||||
delta_first_last: false
|
||||
multi_type: separator
|
||||
separator: ', '
|
||||
field_api_classes: false
|
||||
plugin_id: field
|
||||
entity_type: node
|
||||
entity_field: body
|
||||
filters:
|
||||
title:
|
||||
id: title
|
||||
table: node_field_data
|
||||
field: title
|
||||
relationship: none
|
||||
group_type: group
|
||||
admin_label: ''
|
||||
operator: starts
|
||||
value: ''
|
||||
group: 1
|
||||
exposed: true
|
||||
expose:
|
||||
operator_id: title_op
|
||||
label: Title
|
||||
description: ''
|
||||
use_operator: false
|
||||
operator: title_op
|
||||
identifier: title
|
||||
required: false
|
||||
remember: false
|
||||
multiple: false
|
||||
remember_roles:
|
||||
authenticated: authenticated
|
||||
anonymous: '0'
|
||||
administrator: '0'
|
||||
is_grouped: false
|
||||
group_info:
|
||||
label: ''
|
||||
description: ''
|
||||
identifier: ''
|
||||
optional: true
|
||||
widget: select
|
||||
multiple: false
|
||||
remember: false
|
||||
default_group: All
|
||||
default_group_multiple: { }
|
||||
group_items: { }
|
||||
entity_type: node
|
||||
entity_field: title
|
||||
plugin_id: string
|
||||
title: 'Test serialize'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
style: false
|
||||
row: false
|
||||
path: test/serialize/node-exposed-filter
|
||||
access:
|
||||
type: none
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_field
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
langcode: en
|
||||
status: true
|
||||
dependencies:
|
||||
module:
|
||||
- rest
|
||||
- user
|
||||
id: test_serializer_shared_path
|
||||
label: 'Test serializer shared path'
|
||||
module: rest
|
||||
description: ''
|
||||
tag: ''
|
||||
base_table: entity_test
|
||||
base_field: id
|
||||
core: 8.x
|
||||
display:
|
||||
default:
|
||||
display_plugin: default
|
||||
id: default
|
||||
display_title: Master
|
||||
position: null
|
||||
display_options:
|
||||
access:
|
||||
type: perm
|
||||
options:
|
||||
perm: 'access content'
|
||||
cache:
|
||||
type: tag
|
||||
query:
|
||||
type: views_query
|
||||
exposed_form:
|
||||
type: basic
|
||||
style:
|
||||
type: serializer
|
||||
row:
|
||||
type: data_entity
|
||||
sorts:
|
||||
id:
|
||||
id: standard
|
||||
table: entity_test
|
||||
field: id
|
||||
order: DESC
|
||||
plugin_id: date
|
||||
entity_type: entity_test
|
||||
entity_field: id
|
||||
title: 'Test serialize'
|
||||
arguments: { }
|
||||
rest_export_1:
|
||||
display_plugin: rest_export
|
||||
id: rest_export_1
|
||||
display_title: serializer
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
path: test/serialize/shared
|
||||
page_1:
|
||||
display_plugin: page
|
||||
id: page_1
|
||||
display_title: page
|
||||
position: null
|
||||
display_options:
|
||||
defaults:
|
||||
access: false
|
||||
style: false
|
||||
row: false
|
||||
style:
|
||||
type: default
|
||||
row:
|
||||
type: entity:entity_test
|
||||
path: test/serialize/shared
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses testing $auth=NULL, i.e. authless/anon.
|
||||
*
|
||||
* Characteristics:
|
||||
* - When no authentication provider is being used, there also cannot be any
|
||||
* particular error response for missing authentication, since by definition
|
||||
* there is not any authentication.
|
||||
* - For the same reason, there are no authentication edge cases to test.
|
||||
* - Because no authentication is required, this is vulnerable to CSRF attacks
|
||||
* by design. Hence a REST resource should probably only allow for anonymous
|
||||
* for safe (GET/HEAD) HTTP methods, and only with extreme care should unsafe
|
||||
* (POST/PATCH/DELETE) HTTP methods be allowed for a REST resource that allows
|
||||
* anonymous access.
|
||||
*/
|
||||
trait AnonResourceTestTrait {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response) {
|
||||
throw new \LogicException('When testing for anonymous users, authentication cannot be missing.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses testing $auth=basic_auth.
|
||||
*
|
||||
* Characteristics:
|
||||
* - Every request must send an Authorization header.
|
||||
* - When accessing a URI that requires authentication without being
|
||||
* authenticated, a 401 response must be sent.
|
||||
* - Because every request must send an authorization, there is no danger of
|
||||
* CSRF attacks.
|
||||
*
|
||||
* @see \Drupal\Tests\rest\Functional\BasicAuthResourceWithInterfaceTranslationTestTrait
|
||||
*/
|
||||
trait BasicAuthResourceTestTrait {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAuthenticationRequestOptions($method) {
|
||||
return [
|
||||
'headers' => [
|
||||
'Authorization' => 'Basic ' . base64_encode($this->account->name->value . ':' . $this->account->passRaw),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response) {
|
||||
$expected_page_cache_header_value = $method === 'GET' ? 'MISS' : FALSE;
|
||||
// @see \Drupal\basic_auth\Authentication\Provider\BasicAuth::challengeException()
|
||||
$expected_dynamic_page_cache_header_value = $expected_page_cache_header_value;
|
||||
$this->assertResourceErrorResponse(401, 'No authentication credentials provided.', $response, ['4xx-response', 'config:system.site', 'config:user.role.anonymous', 'http_response'], ['user.roles:anonymous'], $expected_page_cache_header_value, $expected_dynamic_page_cache_header_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses testing $auth=basic_auth + 'language'.
|
||||
*
|
||||
* @see \Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait
|
||||
*/
|
||||
trait BasicAuthResourceWithInterfaceTranslationTestTrait {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response) {
|
||||
// Because BasicAuth::challengeException() relies on the 'system.site'
|
||||
// configuration, and this test installs the 'language' module, all config
|
||||
// may be translated and therefore gets the 'languages:language_interface'
|
||||
// cache context.
|
||||
$expected_page_cache_header_value = $method === 'GET' ? 'MISS' : FALSE;
|
||||
$this->assertResourceErrorResponse(401, 'No authentication credentials provided.', $response, ['4xx-response', 'config:system.site', 'config:user.role.anonymous', 'http_response'], ['languages:language_interface', 'user.roles:anonymous'], $expected_page_cache_header_value, $expected_page_cache_header_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses formatting expected timestamp data.
|
||||
*/
|
||||
trait BcTimestampNormalizerUnixTestTrait {
|
||||
|
||||
/**
|
||||
* Formats a UNIX timestamp.
|
||||
*
|
||||
* Depending on the 'bc_timestamp_normalizer_unix' setting. The return will be
|
||||
* an RFC3339 date string or the same timestamp that was passed in.
|
||||
*
|
||||
* @param int $timestamp
|
||||
* The timestamp value to format.
|
||||
*
|
||||
* @return string|int
|
||||
* The formatted RFC3339 date string or UNIX timestamp.
|
||||
*
|
||||
* @see \Drupal\serialization\Normalizer\TimestampItemNormalizer
|
||||
*/
|
||||
protected function formatExpectedTimestampItemValues($timestamp) {
|
||||
// If the setting is enabled, just return the timestamp as-is now.
|
||||
if ($this->config('serialization.settings')->get('bc_timestamp_normalizer_unix')) {
|
||||
return ['value' => $timestamp];
|
||||
}
|
||||
|
||||
// Otherwise, format the date string to the same that
|
||||
// \Drupal\serialization\Normalizer\TimestampItemNormalizer will produce.
|
||||
$date = new \DateTime();
|
||||
$date->setTimestamp($timestamp);
|
||||
$date->setTimezone(new \DateTimeZone('UTC'));
|
||||
|
||||
// Format is also added to the expected return values.
|
||||
return [
|
||||
'value' => $date->format(\DateTime::RFC3339),
|
||||
'format' => \DateTime::RFC3339,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Trait for ResourceTestBase subclasses testing $auth=cookie.
|
||||
*
|
||||
* Characteristics:
|
||||
* - After performing a valid "log in" request, the server responds with a 2xx
|
||||
* status code and a 'Set-Cookie' response header. This cookie is what
|
||||
* continues to identify the user in subsequent requests.
|
||||
* - When accessing a URI that requires authentication without being
|
||||
* authenticated, a standard 403 response must be sent.
|
||||
* - Because of the reliance on cookies, and the fact that user agents send
|
||||
* cookies with every request, this is vulnerable to CSRF attacks. To mitigate
|
||||
* this, the response for the "log in" request contains a CSRF token that must
|
||||
* be sent with every unsafe (POST/PATCH/DELETE) HTTP request.
|
||||
*/
|
||||
trait CookieResourceTestTrait {
|
||||
|
||||
/**
|
||||
* The session cookie.
|
||||
*
|
||||
* @see ::initAuthentication
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sessionCookie;
|
||||
|
||||
/**
|
||||
* The CSRF token.
|
||||
*
|
||||
* @see ::initAuthentication
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $csrfToken;
|
||||
|
||||
/**
|
||||
* The logout token.
|
||||
*
|
||||
* @see ::initAuthentication
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $logoutToken;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function initAuthentication() {
|
||||
$user_login_url = Url::fromRoute('user.login.http')
|
||||
->setRouteParameter('_format', static::$format);
|
||||
|
||||
$request_body = [
|
||||
'name' => $this->account->name->value,
|
||||
'pass' => $this->account->passRaw,
|
||||
];
|
||||
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($request_body, static::$format);
|
||||
$request_options[RequestOptions::HEADERS] = [
|
||||
'Content-Type' => static::$mimeType,
|
||||
];
|
||||
$response = $this->request('POST', $user_login_url, $request_options);
|
||||
|
||||
// Parse and store the session cookie.
|
||||
$this->sessionCookie = explode(';', $response->getHeader('Set-Cookie')[0], 2)[0];
|
||||
|
||||
// Parse and store the CSRF token and logout token.
|
||||
$data = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
$this->csrfToken = $data['csrf_token'];
|
||||
$this->logoutToken = $data['logout_token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAuthenticationRequestOptions($method) {
|
||||
$request_options[RequestOptions::HEADERS]['Cookie'] = $this->sessionCookie;
|
||||
// @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
|
||||
if (!in_array($method, ['HEAD', 'GET', 'OPTIONS', 'TRACE'])) {
|
||||
$request_options[RequestOptions::HEADERS]['X-CSRF-Token'] = $this->csrfToken;
|
||||
}
|
||||
return $request_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response) {
|
||||
// Requests needing cookie authentication but missing it results in a 403
|
||||
// response. The cookie authentication mechanism sets no response message.
|
||||
// Hence, effectively, this is just the 403 response that one gets as the
|
||||
// anonymous user trying to access a certain REST resource.
|
||||
// @see \Drupal\user\Authentication\Provider\Cookie
|
||||
// @todo https://www.drupal.org/node/2847623
|
||||
if ($method === 'GET') {
|
||||
$expected_cookie_403_cacheability = $this->getExpectedUnauthorizedAccessCacheability();
|
||||
// - \Drupal\Core\EventSubscriber\AnonymousUserResponseSubscriber applies
|
||||
// to cacheable anonymous responses: it updates their cacheability.
|
||||
// - A 403 response to a GET request is cacheable.
|
||||
// Therefore we must update our cacheability expectations accordingly.
|
||||
if (in_array('user.permissions', $expected_cookie_403_cacheability->getCacheContexts(), TRUE)) {
|
||||
$expected_cookie_403_cacheability->addCacheTags(['config:user.role.anonymous']);
|
||||
}
|
||||
// @todo Fix \Drupal\block\BlockAccessControlHandler::mergeCacheabilityFromConditions() in https://www.drupal.org/node/2867881
|
||||
if (static::$entityTypeId === 'block') {
|
||||
$expected_cookie_403_cacheability->setCacheTags(str_replace('user:2', 'user:0', $expected_cookie_403_cacheability->getCacheTags()));
|
||||
}
|
||||
$this->assertResourceErrorResponse(403, FALSE, $response, $expected_cookie_403_cacheability->getCacheTags(), $expected_cookie_403_cacheability->getCacheContexts(), 'MISS', 'MISS');
|
||||
}
|
||||
else {
|
||||
$this->assertResourceErrorResponse(403, FALSE, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options) {
|
||||
// X-CSRF-Token request header is unnecessary for safe and side effect-free
|
||||
// HTTP methods. No need for additional assertions.
|
||||
// @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
|
||||
if (in_array($method, ['HEAD', 'GET', 'OPTIONS', 'TRACE'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($request_options[RequestOptions::HEADERS]['X-CSRF-Token']);
|
||||
|
||||
// DX: 403 when missing X-CSRF-Token request header.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
$this->assertResourceErrorResponse(403, 'X-CSRF-Token request header is missing', $response);
|
||||
|
||||
$request_options[RequestOptions::HEADERS]['X-CSRF-Token'] = 'this-is-not-the-token-you-are-looking-for';
|
||||
|
||||
// DX: 403 when invalid X-CSRF-Token request header.
|
||||
$response = $this->request($method, $url, $request_options);
|
||||
$this->assertResourceErrorResponse(403, 'X-CSRF-Token request header is invalid', $response);
|
||||
|
||||
$request_options[RequestOptions::HEADERS]['X-CSRF-Token'] = $this->csrfToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Action;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ActionResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\system\Functional\Rest\ActionResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\system\Functional\Rest\ActionResourceTestBase as ActionResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\system\Functional\Rest\ActionResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ActionResourceTestBase extends ActionResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\BaseFieldOverride;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\BaseFieldOverrideResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\BaseFieldOverrideResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\BaseFieldOverrideResourceTestBase as BaseFieldOverrideResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\BaseFieldOverrideResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class BaseFieldOverrideResourceTestBase extends BaseFieldOverrideResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Block;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\BlockResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\block\Functional\Rest\BlockResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\block\Functional\Rest\BlockResourceTestBase as BlockResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\block\Functional\Rest\BlockResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class BlockResourceTestBase extends BlockResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\BlockContent;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\BlockContentResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\block_content\Functional\Rest\BlockContentResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentResourceTestBase as BlockContentResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\block_content\Functional\Rest\BlockContentResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class BlockContentResourceTestBase extends BlockContentResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\BlockContentType;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\BlockContentTypeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase as BlockContentTypeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\block_content\Functional\Rest\BlockContentTypeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class BlockContentTypeResourceTestBase extends BlockContentTypeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Comment;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\CommentResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\comment\Functional\Rest\CommentResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\comment\Functional\Rest\CommentResourceTestBase as CommentResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\comment\Functional\Rest\CommentResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class CommentResourceTestBase extends CommentResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\CommentType;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\CommentTypeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\comment\Functional\Rest\CommentTypeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\comment\Functional\Rest\CommentTypeResourceTestBase as CommentTypeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\comment\Functional\Rest\CommentTypeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class CommentTypeResourceTestBase extends CommentTypeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ConfigTest;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ConfigTestResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\config_test\Functional\Rest\ConfigTestResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\config_test\Functional\Rest\ConfigTestResourceTestBase as ConfigTestResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\config_test\Functional\Rest\ConfigTestResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ConfigTestResourceTestBase extends ConfigTestResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ConfigurableLanguage;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ConfigurableLanguageResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\language\Functional\Rest\ConfigurableLanguageResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\language\Functional\Rest\ConfigurableLanguageResourceTestBase as ConfigurableLanguageResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\language\Functional\Rest\ConfigurableLanguageResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ConfigurableLanguageResourceTestBase extends ConfigurableLanguageResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContactForm;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ContactFormResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\contact\Functional\Rest\ContactFormResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\contact\Functional\Rest\ContactFormResourceTestBase as ContactFormResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\contact\Functional\Rest\ContactFormResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ContactFormResourceTestBase extends ContactFormResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ContentLanguageSettings;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ContentLanguageSettingsResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\language\Functional\Rest\ContentLanguageSettingsResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\language\Functional\Rest\ContentLanguageSettingsResourceTestBase as ContentLanguageSettingsResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\language\Functional\Rest\ContentLanguageSettingsResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ContentLanguageSettingsResourceTestBase extends ContentLanguageSettingsResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\DateFormat;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\DateFormatResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\DateFormatResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\DateFormatResourceTestBase as DateFormatResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\DateFormatResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class DateFormatResourceTestBase extends DateFormatResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Editor;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EditorResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\editor\Functional\Rest\EditorResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\editor\Functional\Rest\EditorResourceTestBase as EditorResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\editor\Functional\Rest\EditorResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EditorResourceTestBase extends EditorResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormDisplay;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityFormDisplayResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\EntityFormDisplayResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\EntityFormDisplayResourceTestBase as EntityFormDisplayResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\EntityFormDisplayResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityFormDisplayResourceTestBase extends EntityFormDisplayResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityFormMode;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityFormModeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\EntityFormModeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\EntityFormModeResourceTestBase as EntityFormModeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\EntityFormModeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityFormModeResourceTestBase extends EntityFormModeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Checks that all core content/config entity types have REST test coverage.
|
||||
*
|
||||
* Every entity type must have test coverage for:
|
||||
* - every format in core (json + xml + hal_json)
|
||||
* - every authentication provider in core (anon, cookie, basic_auth)
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class EntityResourceRestTestCoverageTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Entity definitions array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$all_modules = system_rebuild_module_data();
|
||||
$stable_core_modules = array_filter($all_modules, function ($module) {
|
||||
// Filter out contrib, hidden, testing, and experimental modules. We also
|
||||
// don't need to enable modules that are already enabled.
|
||||
return
|
||||
$module->origin === 'core' &&
|
||||
empty($module->info['hidden']) &&
|
||||
$module->status == FALSE &&
|
||||
$module->info['package'] !== 'Testing' &&
|
||||
$module->info['package'] !== 'Core (Experimental)';
|
||||
});
|
||||
|
||||
$this->container->get('module_installer')->install(array_keys($stable_core_modules));
|
||||
$this->rebuildContainer();
|
||||
|
||||
$this->definitions = $this->container->get('entity_type.manager')->getDefinitions();
|
||||
|
||||
// Entity types marked as "internal" are not exposed by the entity REST
|
||||
// resource plugin and hence also don't need test coverage.
|
||||
$this->definitions = array_filter($this->definitions, function (EntityTypeInterface $entity_type) {
|
||||
return !$entity_type->isInternal();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all core content/config entity types have REST test coverage.
|
||||
*/
|
||||
public function testEntityTypeRestTestCoverage() {
|
||||
$tests = [
|
||||
// Test coverage for formats provided by the 'serialization' module.
|
||||
'serialization' => [
|
||||
'path' => '\Drupal\Tests\PROVIDER\Functional\Rest\CLASS',
|
||||
'class suffix' => [
|
||||
'JsonAnonTest',
|
||||
'JsonBasicAuthTest',
|
||||
'JsonCookieTest',
|
||||
'XmlAnonTest',
|
||||
'XmlBasicAuthTest',
|
||||
'XmlCookieTest',
|
||||
],
|
||||
],
|
||||
// Test coverage for formats provided by the 'hal' module.
|
||||
'hal' => [
|
||||
'path' => '\Drupal\Tests\PROVIDER\Functional\Hal\CLASS',
|
||||
'class suffix' => [
|
||||
'HalJsonAnonTest',
|
||||
'HalJsonBasicAuthTest',
|
||||
'HalJsonCookieTest',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$problems = [];
|
||||
foreach ($this->definitions as $entity_type_id => $info) {
|
||||
$class_name_full = $info->getClass();
|
||||
$parts = explode('\\', $class_name_full);
|
||||
$class_name = end($parts);
|
||||
$module_name = $parts[1];
|
||||
|
||||
foreach ($tests as $module => $info) {
|
||||
$path = $info['path'];
|
||||
$missing_tests = [];
|
||||
foreach ($info['class suffix'] as $postfix) {
|
||||
$class = str_replace(['PROVIDER', 'CLASS'], [$module_name, $class_name], $path . $postfix);
|
||||
$class_alternative = str_replace("\\Drupal\\Tests\\$module_name\\Functional", '\Drupal\FunctionalTests', $class);
|
||||
if (class_exists($class) || class_exists($class_alternative)) {
|
||||
continue;
|
||||
}
|
||||
$missing_tests[] = $postfix;
|
||||
}
|
||||
if (!empty($missing_tests)) {
|
||||
$missing_tests_list = implode(', ', array_map(function ($missing_test) use ($class_name) {
|
||||
return $class_name . $missing_test;
|
||||
}, $missing_tests));
|
||||
$which_normalization = $module === 'serialization' ? 'default' : $module;
|
||||
$problems[] = "$entity_type_id: $class_name ($class_name_full), $which_normalization normalization (expected tests: $missing_tests_list)";
|
||||
}
|
||||
}
|
||||
}
|
||||
$all = count($this->definitions);
|
||||
$good = $all - count($problems);
|
||||
$this->assertSame([], $problems, $this->getLlamaMessage($good, $all));
|
||||
}
|
||||
|
||||
/**
|
||||
* Message from Llama.
|
||||
*
|
||||
* @param int $g
|
||||
* A count of entities with test coverage.
|
||||
* @param int $a
|
||||
* A count of all entities.
|
||||
*
|
||||
* @return string
|
||||
* An information about progress of REST test coverage.
|
||||
*/
|
||||
protected function getLlamaMessage($g, $a) {
|
||||
return "
|
||||
☼
|
||||
________________________
|
||||
/ Hi! \\
|
||||
| It's llame to not have |
|
||||
| complete REST tests! |
|
||||
| |
|
||||
| Progress: $g/$a. |
|
||||
| ________________________/
|
||||
|/
|
||||
// o
|
||||
l'>
|
||||
ll
|
||||
llama
|
||||
|| ||
|
||||
'' ''
|
||||
";
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTest;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityTestResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase as EntityTestResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\entity_test\Functional\Rest\EntityTestResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityTestResourceTestBase extends EntityTestResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestBundle;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityTestBundleResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\entity_test\Functional\Rest\EntityTestBundleResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\entity_test\Functional\Rest\EntityTestBundleResourceTestBase as EntityTestBundleResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\entity_test\Functional\Rest\EntityTestBundleResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityTestBundleResourceTestBase extends EntityTestBundleResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityTestLabel;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityTestLabelResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\entity_test\Functional\Rest\EntityTestLabelResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\entity_test\Functional\Rest\EntityTestLabelResourceTestBase as EntityTestLabelResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\entity_test\Functional\Rest\EntityTestLabelResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityTestLabelResourceTestBase extends EntityTestLabelResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewDisplay;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityViewDisplayResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\EntityViewDisplayResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\EntityViewDisplayResourceTestBase as EntityViewDisplayResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\EntityViewDisplayResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityViewDisplayResourceTestBase extends EntityViewDisplayResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\EntityViewMode;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\EntityViewModeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\FunctionalTests\Rest\EntityViewModeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\FunctionalTests\Rest\EntityViewModeResourceTestBase as EntityViewModeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\FunctionalTests\Rest\EntityViewModeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class EntityViewModeResourceTestBase extends EntityViewModeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Feed;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FeedResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\aggregator\Functional\Rest\FeedResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\aggregator\Functional\Rest\FeedResourceTestBase as FeedResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\aggregator\Functional\Rest\FeedResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class FeedResourceTestBase extends FeedResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldConfig;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FieldConfigResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase as FieldConfigResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\field\Functional\Rest\FieldConfigResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class FieldConfigResourceTestBase extends FieldConfigResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FieldStorageConfig;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FieldStorageConfigResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase as FieldStorageConfigResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\field\Functional\Rest\FieldStorageConfigResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class FieldStorageConfigResourceTestBase extends FieldStorageConfigResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\File;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FileResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\file\Functional\Rest\FileResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\file\Functional\Rest\FileResourceTestBase as FileResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\file\Functional\Rest\FileResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class FileResourceTestBase extends FileResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\FilterFormat;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\FilterFormatResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\filter\Functional\Rest\FilterFormatResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\filter\Functional\Rest\FilterFormatResourceTestBase as FilterFormatResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\filter\Functional\Rest\FilterFormatResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class FilterFormatResourceTestBase extends FilterFormatResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
|
||||
/**
|
||||
* Provides test methods to assert BC on format-specific GET routes.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
trait FormatSpecificGetBcRouteTestTrait {
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*
|
||||
* @see \Drupal\rest\RouteProcessor\RestResourceGetRouteProcessorBC
|
||||
*/
|
||||
public function testFormatSpecificGetBcRoute() {
|
||||
$this->provisionEntityResource();
|
||||
$url = $this->getEntityResourceUrl();
|
||||
|
||||
// BC: Format-specific GET routes are deprecated. They are available on both
|
||||
// new and old sites, but trigger deprecation notices.
|
||||
$bc_route = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format, $url->getRouteParameters(), $url->getOptions());
|
||||
$bc_route->setUrlGenerator($this->container->get('url_generator'));
|
||||
$this->expectDeprecation(sprintf("The 'rest.entity.entity_test.GET.%s' route is deprecated since version 8.5.x and will be removed in 9.0.0. Use the 'rest.entity.entity_test.GET' route instead.", static::$format));
|
||||
$this->assertSame($url->toString(TRUE)->getGeneratedUrl(), $bc_route->toString(TRUE)->getGeneratedUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*
|
||||
* @see \Drupal\rest\Plugin\ResourceBase::routes
|
||||
*/
|
||||
public function testNoFormatSpecificGetBcRouteForOtherFormats() {
|
||||
$this->setExpectedException(RouteNotFoundException::class);
|
||||
|
||||
$this->provisionEntityResource();
|
||||
$url = $this->getEntityResourceUrl();
|
||||
|
||||
// Verify no format-specific GET BC routes are created for other formats.
|
||||
$other_format = static::$format === 'json' ? 'xml' : 'json';
|
||||
$bc_route_other_format = Url::fromRoute('rest.entity.entity_test.GET.' . $other_format, $url->getRouteParameters(), $url->getOptions());
|
||||
$bc_route_other_format->setUrlGenerator($this->container->get('url_generator'));
|
||||
$bc_route_other_format->toString(TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ImageStyle;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ImageStyleResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\image\Functional\Rest\ImageStyleResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\image\Functional\Rest\ImageStyleResourceTestBase as ImageStyleResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\image\Functional\Rest\ImageStyleResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ImageStyleResourceTestBase extends ImageStyleResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Item;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ItemResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\aggregator\Functional\Rest\ItemResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\aggregator\Functional\Rest\ItemResourceTestBase as ItemResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\aggregator\Functional\Rest\ItemResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ItemResourceTestBase extends ItemResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Media;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MediaResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\media\Functional\Rest\MediaResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\media\Functional\Rest\MediaResourceTestBase as MediaResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\media\Functional\Rest\MediaResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class MediaResourceTestBase extends MediaResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MediaType;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MediaTypeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\media\Functional\Rest\MediaTypeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\media\Functional\Rest\MediaTypeResourceTestBase as MediaTypeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\media\Functional\Rest\MediaTypeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class MediaTypeResourceTestBase extends MediaTypeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Menu;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MenuResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\system\Functional\Rest\MenuResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\system\Functional\Rest\MenuResourceTestBase as MenuResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\system\Functional\Rest\MenuResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class MenuResourceTestBase extends MenuResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\MenuLinkContent;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MenuLinkContentResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\menu_link_content\Functional\Rest\MenuLinkContentResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\menu_link_content\Functional\Rest\MenuLinkContentResourceTestBase as MenuLinkContentResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\menu_link_content\Functional\Rest\MenuLinkContentResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class MenuLinkContentResourceTestBase extends MenuLinkContentResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Message;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\MessageResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\contact\Functional\Rest\MessageResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\contact\Functional\Rest\MessageResourceTestBase as MessageResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\contact\Functional\Rest\MessageResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class MessageResourceTestBase extends MessageResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeJsonAnonTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeJsonBasicAuthTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeJsonCookieTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
|
||||
use Drupal\Tests\node\Functional\Rest\NodeResourceTestBase;
|
||||
|
||||
/**
|
||||
* Extend the Node resource test base and apply moderation to the entity.
|
||||
*/
|
||||
abstract class ModeratedNodeResourceTestBase extends NodeResourceTestBase {
|
||||
|
||||
use ContentModerationTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['content_moderation'];
|
||||
|
||||
/**
|
||||
* The test editorial workflow.
|
||||
*
|
||||
* @var \Drupal\workflows\WorkflowInterface
|
||||
*/
|
||||
protected $workflow;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
parent::setUpAuthorization($method);
|
||||
|
||||
switch ($method) {
|
||||
case 'POST':
|
||||
case 'PATCH':
|
||||
case 'DELETE':
|
||||
$this->grantPermissionsToTestedRole(['use editorial transition publish', 'use editorial transition create_new_draft']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$entity = parent::createEntity();
|
||||
if (!$this->workflow) {
|
||||
$this->workflow = $this->createEditorialWorkflow();
|
||||
}
|
||||
$this->workflow->getTypePlugin()->addEntityTypeAndBundle($entity->getEntityTypeId(), $entity->bundle());
|
||||
$this->workflow->save();
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return array_merge(parent::getExpectedNormalizedEntity(), [
|
||||
'moderation_state' => [
|
||||
[
|
||||
'value' => 'published',
|
||||
],
|
||||
],
|
||||
'vid' => [
|
||||
[
|
||||
'value' => (int) $this->entity->getRevisionId(),
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeXmlAnonTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPatchPath() {
|
||||
// Deserialization of the XML format is not supported.
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeXmlBasicAuthTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPatchPath() {
|
||||
// Deserialization of the XML format is not supported.
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ModeratedNode;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class ModeratedNodeXmlCookieTest extends ModeratedNodeResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPatchPath() {
|
||||
// Deserialization of the XML format is not supported.
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Node;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\NodeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\node\Functional\Rest\NodeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\node\Functional\Rest\NodeResourceTestBase as NodeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\node\Functional\Rest\NodeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class NodeResourceTestBase extends NodeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\NodeType;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\NodeTypeResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\node\Functional\Rest\NodeTypeResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\node\Functional\Rest\NodeTypeResourceTestBase as NodeTypeResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\node\Functional\Rest\NodeTypeResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class NodeTypeResourceTestBase extends NodeTypeResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\RdfMapping;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\RdfMappingResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\rdf\Functional\Rest\RdfMappingResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\rdf\Functional\Rest\RdfMappingResourceTestBase as RdfMappingResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\rdf\Functional\Rest\RdfMappingResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class RdfMappingResourceTestBase extends RdfMappingResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ResponsiveImageStyle;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ResponsiveImageStyleResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\responsive_image\Functional\Rest\ResponsiveImageStyleResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\responsive_image\Functional\Rest\ResponsiveImageStyleResourceTestBase as ResponsiveImageStyleResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\responsive_image\Functional\Rest\ResponsiveImageStyleResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ResponsiveImageStyleResourceTestBase extends ResponsiveImageStyleResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\RestResourceConfig;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\RestResourceConfigResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase as RestResourceConfigResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class RestResourceConfigResourceTestBase extends RestResourceConfigResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Role;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\RoleResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\user\Functional\Rest\RoleResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\user\Functional\Rest\RoleResourceTestBase as RoleResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\user\Functional\Rest\RoleResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class RoleResourceTestBase extends RoleResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\SearchPage;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\SearchPageResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase as SearchPageResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\search\Functional\Rest\SearchPageResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class SearchPageResourceTestBase extends SearchPageResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Shortcut;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ShortcutResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\shortcut\Functional\Rest\ShortcutResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\shortcut\Functional\Rest\ShortcutResourceTestBase as ShortcutResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\shortcut\Functional\Rest\ShortcutResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ShortcutResourceTestBase extends ShortcutResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\ShortcutSet;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ShortcutSetResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\shortcut\Functional\Rest\ShortcutSetResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\shortcut\Functional\Rest\ShortcutSetResourceTestBase as ShortcutSetResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\shortcut\Functional\Rest\ShortcutSetResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ShortcutSetResourceTestBase extends ShortcutSetResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Term;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\TermResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\taxonomy\Functional\Rest\TermResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\taxonomy\Functional\Rest\TermResourceTestBase as TermResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\taxonomy\Functional\Rest\TermResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class TermResourceTestBase extends TermResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Tour;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\TourResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\tour\Functional\Rest\TourResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\tour\Functional\Rest\TourResourceTestBase as TourResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\tour\Functional\Rest\TourResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class TourResourceTestBase extends TourResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\User;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\UserResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\user\Functional\Rest\UserResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\user\Functional\Rest\UserResourceTestBase as UserResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\user\Functional\Rest\UserResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class UserResourceTestBase extends UserResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\View;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\ViewResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\views\Functional\Rest\ViewResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\views\Functional\Rest\ViewResourceTestBase as ViewResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\views\Functional\Rest\ViewResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class ViewResourceTestBase extends ViewResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource\Vocabulary;
|
||||
|
||||
@trigger_error('The ' . __NAMESPACE__ . '\VocabularyResourceTestBase is deprecated in Drupal 8.6.x and will be removed before Drupal 9.0.0. Instead, use Drupal\Tests\taxonomy\Functional\Rest\VocabularyResourceTestBase. See https://www.drupal.org/node/2971931.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\Tests\taxonomy\Functional\Rest\VocabularyResourceTestBase as VocabularyResourceTestBaseReal;
|
||||
|
||||
/**
|
||||
* @deprecated in Drupal 8.6.x. Will be removed before Drupal 9.0.0. Use
|
||||
* Drupal\Tests\taxonomy\Functional\Rest\VocabularyResourceTestBase instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2971931
|
||||
*/
|
||||
abstract class VocabularyResourceTestBase extends VocabularyResourceTestBaseReal {
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\EntityResource;
|
||||
|
||||
use Drupal\Core\Entity\FieldableEntityInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\ChangedItem;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\CreatedItem;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\IntegerItem;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\TimestampItem;
|
||||
use Drupal\file\Plugin\Field\FieldType\FileItem;
|
||||
use Drupal\image\Plugin\Field\FieldType\ImageItem;
|
||||
use Drupal\options\Plugin\Field\FieldType\ListIntegerItem;
|
||||
use Drupal\path\Plugin\Field\FieldType\PathItem;
|
||||
use Drupal\Tests\rest\Functional\XmlNormalizationQuirksTrait;
|
||||
use Drupal\user\StatusItem;
|
||||
|
||||
/**
|
||||
* Trait for EntityResourceTestBase subclasses testing $format='xml'.
|
||||
*/
|
||||
trait XmlEntityNormalizationQuirksTrait {
|
||||
|
||||
use XmlNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
$default_normalization = parent::getExpectedNormalizedEntity();
|
||||
|
||||
if ($this->entity instanceof FieldableEntityInterface) {
|
||||
$normalization = $this->applyXmlFieldDecodingQuirks($default_normalization);
|
||||
}
|
||||
else {
|
||||
$normalization = $this->applyXmlConfigEntityDecodingQuirks($default_normalization);
|
||||
}
|
||||
$normalization = $this->applyXmlDecodingQuirks($normalization);
|
||||
|
||||
return $normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the XML entity field encoding quirks that remain after decoding.
|
||||
*
|
||||
* The XML encoding:
|
||||
* - loses type data (int and bool become string)
|
||||
*
|
||||
* @param array $normalization
|
||||
* An entity normalization.
|
||||
*
|
||||
* @return array
|
||||
* The updated fieldable entity normalization.
|
||||
*
|
||||
* @see \Symfony\Component\Serializer\Encoder\XmlEncoder
|
||||
*/
|
||||
protected function applyXmlFieldDecodingQuirks(array $normalization) {
|
||||
foreach ($this->entity->getFields(TRUE) as $field_name => $field) {
|
||||
// Not every field is accessible.
|
||||
if (!isset($normalization[$field_name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($normalization[$field_name]); $i++) {
|
||||
switch ($field->getItemDefinition()->getClass()) {
|
||||
case BooleanItem::class:
|
||||
case StatusItem::class:
|
||||
// @todo Remove the StatusItem case in
|
||||
// https://www.drupal.org/project/drupal/issues/2936864.
|
||||
$value = &$normalization[$field_name][$i]['value'];
|
||||
$value = $value === TRUE ? '1' : '0';
|
||||
break;
|
||||
case IntegerItem::class:
|
||||
case ListIntegerItem::class:
|
||||
$value = &$normalization[$field_name][$i]['value'];
|
||||
$value = (string) $value;
|
||||
break;
|
||||
case PathItem::class:
|
||||
$pid = &$normalization[$field_name][$i]['pid'];
|
||||
$pid = (string) $pid;
|
||||
break;
|
||||
case EntityReferenceItem::class:
|
||||
case FileItem::class:
|
||||
$target_id = &$normalization[$field_name][$i]['target_id'];
|
||||
$target_id = (string) $target_id;
|
||||
break;
|
||||
case ChangedItem::class:
|
||||
case CreatedItem::class:
|
||||
case TimestampItem::class:
|
||||
$value = &$normalization[$field_name][$i]['value'];
|
||||
if (is_numeric($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
break;
|
||||
case ImageItem::class:
|
||||
$height = &$normalization[$field_name][$i]['height'];
|
||||
$height = (string) $height;
|
||||
$width = &$normalization[$field_name][$i]['width'];
|
||||
$width = (string) $width;
|
||||
$target_id = &$normalization[$field_name][$i]['target_id'];
|
||||
$target_id = (string) $target_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($normalization[$field_name]) === 1) {
|
||||
$normalization[$field_name] = $normalization[$field_name][0];
|
||||
}
|
||||
}
|
||||
|
||||
return $normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the XML config entity encoding quirks that remain after decoding.
|
||||
*
|
||||
* The XML encoding:
|
||||
* - loses type data (int and bool become string)
|
||||
* - converts single-item arrays into single items (non-arrays)
|
||||
*
|
||||
* @param array $normalization
|
||||
* An entity normalization.
|
||||
*
|
||||
* @return array
|
||||
* The updated config entity normalization.
|
||||
*
|
||||
* @see \Symfony\Component\Serializer\Encoder\XmlEncoder
|
||||
*/
|
||||
protected function applyXmlConfigEntityDecodingQuirks(array $normalization) {
|
||||
$normalization = static::castToString($normalization);
|
||||
|
||||
// When a single dependency is listed, it's not decoded into an array.
|
||||
if (isset($normalization['dependencies'])) {
|
||||
foreach ($normalization['dependencies'] as $dependency_type => $dependency_list) {
|
||||
if (count($dependency_list) === 1) {
|
||||
$normalization['dependencies'][$dependency_type] = $dependency_list[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPost() {
|
||||
// Deserialization of the XML format is not supported.
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function testPatch() {
|
||||
// Deserialization of the XML format is not supported.
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,720 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Component\Render\PlainTextOutput;
|
||||
use Drupal\Component\Utility\NestedArray;
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
use Drupal\user\Entity\User;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Tests binary data file upload route.
|
||||
*/
|
||||
abstract class FileUploadResourceTestBase extends ResourceTestBase {
|
||||
|
||||
use BcTimestampNormalizerUnixTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['rest_test', 'entity_test', 'file'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $resourceConfigId = 'file.upload';
|
||||
|
||||
/**
|
||||
* The POST URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $postUri = 'file/upload/entity_test/entity_test/field_rest_file_test';
|
||||
|
||||
/**
|
||||
* Test file data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $testFileData = 'Hares sit on chairs, and mules sit on stools.';
|
||||
|
||||
/**
|
||||
* The test field storage config.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldStorageConfig
|
||||
*/
|
||||
protected $fieldStorage;
|
||||
|
||||
/**
|
||||
* The field config.
|
||||
*
|
||||
* @var \Drupal\field\Entity\FieldConfig
|
||||
*/
|
||||
protected $field;
|
||||
|
||||
/**
|
||||
* The parent entity.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* Created file entity.
|
||||
*
|
||||
* @var \Drupal\file\Entity\File
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* An authenticated user.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* The entity storage for the 'file' entity type.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $fileStorage;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->fileStorage = $this->container->get('entity_type.manager')
|
||||
->getStorage('file');
|
||||
|
||||
// Add a file field.
|
||||
$this->fieldStorage = FieldStorageConfig::create([
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_rest_file_test',
|
||||
'type' => 'file',
|
||||
'settings' => [
|
||||
'uri_scheme' => 'public',
|
||||
],
|
||||
])
|
||||
->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
$this->fieldStorage->save();
|
||||
|
||||
$this->field = FieldConfig::create([
|
||||
'entity_type' => 'entity_test',
|
||||
'field_name' => 'field_rest_file_test',
|
||||
'bundle' => 'entity_test',
|
||||
'settings' => [
|
||||
'file_directory' => 'foobar',
|
||||
'file_extensions' => 'txt',
|
||||
'max_filesize' => '',
|
||||
],
|
||||
])
|
||||
->setLabel('Test file field')
|
||||
->setTranslatable(FALSE);
|
||||
$this->field->save();
|
||||
|
||||
// Create an entity that a file can be attached to.
|
||||
$this->entity = EntityTest::create([
|
||||
'name' => 'Llama',
|
||||
'type' => 'entity_test',
|
||||
]);
|
||||
$this->entity->setOwnerId(isset($this->account) ? $this->account->id() : 0);
|
||||
$this->entity->save();
|
||||
|
||||
// Provision entity_test resource.
|
||||
$this->resourceConfigStorage->create([
|
||||
'id' => 'entity.entity_test',
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => ['POST'],
|
||||
'formats' => [static::$format],
|
||||
'authentication' => [static::$auth],
|
||||
],
|
||||
'status' => TRUE,
|
||||
])->save();
|
||||
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload POST route.
|
||||
*/
|
||||
public function testPostFileUpload() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// DX: 403 when unauthorized.
|
||||
$response = $this->fileRequest($uri, $this->testFileData);
|
||||
$this->assertResourceErrorResponse(403, $this->getExpectedUnauthorizedAccessMessage('POST'), $response);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
// 404 when the field name is invalid.
|
||||
$invalid_uri = Url::fromUri('base:file/upload/entity_test/entity_test/field_rest_file_test_invalid');
|
||||
$response = $this->fileRequest($invalid_uri, $this->testFileData);
|
||||
$this->assertResourceErrorResponse(404, 'Field "field_rest_file_test_invalid" does not exist', $response);
|
||||
|
||||
// This request will have the default 'application/octet-stream' content
|
||||
// type header.
|
||||
$response = $this->fileRequest($uri, $this->testFileData);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example.txt'));
|
||||
|
||||
// Test the file again but using 'filename' in the Content-Disposition
|
||||
// header with no 'file' prefix.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'filename="example.txt"']);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity(2, 'example_0.txt');
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example_0.txt'));
|
||||
$this->assertTrue($this->fileStorage->loadUnchanged(1)->isTemporary());
|
||||
|
||||
// Verify that we can create an entity that references the uploaded file.
|
||||
$entity_test_post_url = Url::fromRoute('rest.entity.entity_test.POST')
|
||||
->setOption('query', ['_format' => static::$format]);
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;
|
||||
$request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST'));
|
||||
|
||||
$request_options[RequestOptions::BODY] = $this->serializer->encode($this->getNormalizedPostEntity(), static::$format);
|
||||
$response = $this->request('POST', $entity_test_post_url, $request_options);
|
||||
$this->assertResourceResponse(201, FALSE, $response);
|
||||
$this->assertTrue($this->fileStorage->loadUnchanged(1)->isPermanent());
|
||||
$this->assertSame([
|
||||
[
|
||||
'target_id' => '1',
|
||||
'display' => NULL,
|
||||
'description' => "The most fascinating file ever!",
|
||||
],
|
||||
], EntityTest::load(2)->get('field_rest_file_test')->getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized POST entity referencing the uploaded file.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see ::testPostFileUpload()
|
||||
* @see \Drupal\Tests\rest\Functional\EntityResource\EntityTest\EntityTestResourceTestBase::getNormalizedPostEntity()
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
return [
|
||||
'type' => [
|
||||
[
|
||||
'value' => 'entity_test',
|
||||
],
|
||||
],
|
||||
'name' => [
|
||||
[
|
||||
'value' => 'Dramallama',
|
||||
],
|
||||
],
|
||||
'field_rest_file_test' => [
|
||||
[
|
||||
'target_id' => 1,
|
||||
'description' => 'The most fascinating file ever!',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload POST route with invalid headers.
|
||||
*/
|
||||
public function testPostFileUploadInvalidHeaders() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// The wrong content type header should return a 415 code.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Type' => static::$mimeType]);
|
||||
$this->assertResourceErrorResponse(415, sprintf('No route found that matches "Content-Type: %s"', static::$mimeType), $response);
|
||||
|
||||
// An empty Content-Disposition header should return a 400.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => '']);
|
||||
$this->assertResourceErrorResponse(400, '"Content-Disposition" header is required. A file name in the format "filename=FILENAME" must be provided', $response);
|
||||
|
||||
// An empty filename with a context in the Content-Disposition header should
|
||||
// return a 400.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename=""']);
|
||||
$this->assertResourceErrorResponse(400, 'No filename found in "Content-Disposition" header. A file name in the format "filename=FILENAME" must be provided', $response);
|
||||
|
||||
// An empty filename without a context in the Content-Disposition header
|
||||
// should return a 400.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'filename=""']);
|
||||
$this->assertResourceErrorResponse(400, 'No filename found in "Content-Disposition" header. A file name in the format "filename=FILENAME" must be provided', $response);
|
||||
|
||||
// An invalid key-value pair in the Content-Disposition header should return
|
||||
// a 400.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'not_a_filename="example.txt"']);
|
||||
$this->assertResourceErrorResponse(400, 'No filename found in "Content-Disposition" header. A file name in the format "filename=FILENAME" must be provided', $response);
|
||||
|
||||
// Using filename* extended format is not currently supported.
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'filename*="UTF-8 \' \' example.txt"']);
|
||||
$this->assertResourceErrorResponse(400, 'The extended "filename*" format is currently not supported in the "Content-Disposition" header', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload POST route with a duplicate file name.
|
||||
*
|
||||
* A new file should be created with a suffixed name.
|
||||
*/
|
||||
public function testPostFileUploadDuplicateFile() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// This request will have the default 'application/octet-stream' content
|
||||
// type header.
|
||||
$response = $this->fileRequest($uri, $this->testFileData);
|
||||
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
|
||||
// Make the same request again. The file should be saved as a new file
|
||||
// entity that has the same file name but a suffixed file URI.
|
||||
$response = $this->fileRequest($uri, $this->testFileData);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
|
||||
// Loading expected normalized data for file 2, the duplicate file.
|
||||
$expected = $this->getExpectedNormalizedEntity(2, 'example_0.txt');
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example_0.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload route with any path prefixes being stripped.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives
|
||||
*/
|
||||
public function testFileUploadStrippedFilePath() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename="directory/example.txt"']);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data. It should have been written to the configured
|
||||
// directory, not /foobar/directory/example.txt.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example.txt'));
|
||||
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename="../../example_2.txt"']);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity(2, 'example_2.txt', TRUE);
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data. It should have been written to the configured
|
||||
// directory, not /foobar/directory/example.txt.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example_2.txt'));
|
||||
$this->assertFalse(file_exists('../../example_2.txt'));
|
||||
|
||||
// Check a path from the root. Extensions have to be empty to allow a file
|
||||
// with no extension to pass validation.
|
||||
$this->field->setSetting('file_extensions', '')
|
||||
->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename="/etc/passwd"']);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity(3, 'passwd', TRUE);
|
||||
// This mime will be guessed as there is no extension.
|
||||
$expected['filemime'][0]['value'] = 'application/octet-stream';
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data. It should have been written to the configured
|
||||
// directory, not /foobar/directory/example.txt.
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/passwd'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload route with a unicode file name.
|
||||
*/
|
||||
public function testFileUploadUnicodeFilename() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'file; filename="example-✓.txt"']);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity(1, 'example-✓.txt', TRUE);
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertSame($this->testFileData, file_get_contents('public://foobar/example-✓.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload route with a zero byte file.
|
||||
*/
|
||||
public function testFileUploadZeroByteFile() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// Test with a zero byte file.
|
||||
$response = $this->fileRequest($uri, NULL);
|
||||
$this->assertSame(201, $response->getStatusCode());
|
||||
$expected = $this->getExpectedNormalizedEntity();
|
||||
// Modify the default expected data to account for the 0 byte file.
|
||||
$expected['filesize'][0]['value'] = 0;
|
||||
$this->assertResponseData($expected, $response);
|
||||
|
||||
// Check the actual file data.
|
||||
$this->assertSame('', file_get_contents('public://foobar/example.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload route with an invalid file type.
|
||||
*/
|
||||
public function testFileUploadInvalidFileType() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// Test with a JSON file.
|
||||
$response = $this->fileRequest($uri, '{"test":123}', ['Content-Disposition' => 'filename="example.json"']);
|
||||
$this->assertResourceErrorResponse(422, PlainTextOutput::renderFromHtml("Unprocessable Entity: file validation failed.\nOnly files with the following extensions are allowed: <em class=\"placeholder\">txt</em>."), $response);
|
||||
|
||||
// Make sure that no file was saved.
|
||||
$this->assertEmpty(File::load(1));
|
||||
$this->assertFalse(file_exists('public://foobar/example.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload route with a file size larger than allowed.
|
||||
*/
|
||||
public function testFileUploadLargerFileSize() {
|
||||
// Set a limit of 50 bytes.
|
||||
$this->field->setSetting('max_filesize', 50)
|
||||
->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
// Generate a string larger than the 50 byte limit set.
|
||||
$response = $this->fileRequest($uri, $this->randomString(100));
|
||||
$this->assertResourceErrorResponse(422, PlainTextOutput::renderFromHtml("Unprocessable Entity: file validation failed.\nThe file is <em class=\"placeholder\">100 bytes</em> exceeding the maximum file size of <em class=\"placeholder\">50 bytes</em>."), $response);
|
||||
|
||||
// Make sure that no file was saved.
|
||||
$this->assertEmpty(File::load(1));
|
||||
$this->assertFalse(file_exists('public://foobar/example.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload POST route with malicious extensions.
|
||||
*/
|
||||
public function testFileUploadMaliciousExtension() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
// Allow all file uploads but system.file::allow_insecure_uploads is set to
|
||||
// FALSE.
|
||||
$this->field->setSetting('file_extensions', '')->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
$php_string = '<?php print "Drupal"; ?>';
|
||||
|
||||
// Test using a masked exploit file.
|
||||
$response = $this->fileRequest($uri, $php_string, ['Content-Disposition' => 'filename="example.php"']);
|
||||
// The filename is not munged because .txt is added and it is a known
|
||||
// extension to apache.
|
||||
$expected = $this->getExpectedNormalizedEntity(1, 'example.php.txt', TRUE);
|
||||
// Override the expected filesize.
|
||||
$expected['filesize'][0]['value'] = strlen($php_string);
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertTrue(file_exists('public://foobar/example.php.txt'));
|
||||
|
||||
// Add php as an allowed format. Allow insecure uploads still being FALSE
|
||||
// should still not allow this. So it should still have a .txt extension
|
||||
// appended even though it is not in the list of allowed extensions.
|
||||
$this->field->setSetting('file_extensions', 'php')
|
||||
->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$response = $this->fileRequest($uri, $php_string, ['Content-Disposition' => 'filename="example_2.php"']);
|
||||
$expected = $this->getExpectedNormalizedEntity(2, 'example_2.php.txt', TRUE);
|
||||
// Override the expected filesize.
|
||||
$expected['filesize'][0]['value'] = strlen($php_string);
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertTrue(file_exists('public://foobar/example_2.php.txt'));
|
||||
$this->assertFalse(file_exists('public://foobar/example_2.php'));
|
||||
|
||||
// Allow .doc file uploads and ensure even a mis-configured apache will not
|
||||
// fallback to php because the filename will be munged.
|
||||
$this->field->setSetting('file_extensions', 'doc')->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
// Test using a masked exploit file.
|
||||
$response = $this->fileRequest($uri, $php_string, ['Content-Disposition' => 'filename="example_3.php.doc"']);
|
||||
// The filename is munged.
|
||||
$expected = $this->getExpectedNormalizedEntity(3, 'example_3.php_.doc', TRUE);
|
||||
// Override the expected filesize.
|
||||
$expected['filesize'][0]['value'] = strlen($php_string);
|
||||
// The file mime should be 'application/msword'.
|
||||
$expected['filemime'][0]['value'] = 'application/msword';
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertTrue(file_exists('public://foobar/example_3.php_.doc'));
|
||||
$this->assertFalse(file_exists('public://foobar/example_3.php.doc'));
|
||||
|
||||
// Now allow insecure uploads.
|
||||
\Drupal::configFactory()
|
||||
->getEditable('system.file')
|
||||
->set('allow_insecure_uploads', TRUE)
|
||||
->save();
|
||||
// Allow all file uploads. This is very insecure.
|
||||
$this->field->setSetting('file_extensions', '')->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$response = $this->fileRequest($uri, $php_string, ['Content-Disposition' => 'filename="example_4.php"']);
|
||||
$expected = $this->getExpectedNormalizedEntity(4, 'example_4.php', TRUE);
|
||||
// Override the expected filesize.
|
||||
$expected['filesize'][0]['value'] = strlen($php_string);
|
||||
// The file mime should also now be PHP.
|
||||
$expected['filemime'][0]['value'] = 'application/x-httpd-php';
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertTrue(file_exists('public://foobar/example_4.php'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests using the file upload POST route no extension configured.
|
||||
*/
|
||||
public function testFileUploadNoExtensionSetting() {
|
||||
$this->initAuthentication();
|
||||
|
||||
$this->provisionResource([static::$format], static::$auth ? [static::$auth] : [], ['POST']);
|
||||
|
||||
$this->setUpAuthorization('POST');
|
||||
|
||||
$uri = Url::fromUri('base:' . static::$postUri);
|
||||
|
||||
$this->field->setSetting('file_extensions', '')
|
||||
->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
|
||||
$response = $this->fileRequest($uri, $this->testFileData, ['Content-Disposition' => 'filename="example.txt"']);
|
||||
$expected = $this->getExpectedNormalizedEntity(1, 'example.txt', TRUE);
|
||||
|
||||
$this->assertResponseData($expected, $response);
|
||||
$this->assertTrue(file_exists('public://foobar/example.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {
|
||||
// The file upload resource only accepts binary data, so there are no
|
||||
// normalization edge cases to test, as there are no normalized entity
|
||||
// representations incoming.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
return "The following permissions are required: 'administer entity_test content' OR 'administer entity_test_with_bundle content' OR 'create entity_test entity_test_with_bundle entities'.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expected file entity.
|
||||
*
|
||||
* @param int $fid
|
||||
* The file ID to load and create normalized data for.
|
||||
* @param string $expected_filename
|
||||
* The expected filename for the stored file.
|
||||
* @param bool $expected_as_filename
|
||||
* Whether the expected filename should be the filename property too.
|
||||
*
|
||||
* @return array
|
||||
* The expected normalized data array.
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity($fid = 1, $expected_filename = 'example.txt', $expected_as_filename = FALSE) {
|
||||
$author = User::load(static::$auth ? $this->account->id() : 0);
|
||||
$file = File::load($fid);
|
||||
|
||||
$expected_normalization = [
|
||||
'fid' => [
|
||||
[
|
||||
'value' => (int) $file->id(),
|
||||
],
|
||||
],
|
||||
'uuid' => [
|
||||
[
|
||||
'value' => $file->uuid(),
|
||||
],
|
||||
],
|
||||
'langcode' => [
|
||||
[
|
||||
'value' => 'en',
|
||||
],
|
||||
],
|
||||
'uid' => [
|
||||
[
|
||||
'target_id' => (int) $author->id(),
|
||||
'target_type' => 'user',
|
||||
'target_uuid' => $author->uuid(),
|
||||
'url' => base_path() . 'user/' . $author->id(),
|
||||
],
|
||||
],
|
||||
'filename' => [
|
||||
[
|
||||
'value' => $expected_as_filename ? $expected_filename : 'example.txt',
|
||||
],
|
||||
],
|
||||
'uri' => [
|
||||
[
|
||||
'value' => 'public://foobar/' . $expected_filename,
|
||||
'url' => base_path() . $this->siteDirectory . '/files/foobar/' . rawurlencode($expected_filename),
|
||||
],
|
||||
],
|
||||
'filemime' => [
|
||||
[
|
||||
'value' => 'text/plain',
|
||||
],
|
||||
],
|
||||
'filesize' => [
|
||||
[
|
||||
'value' => strlen($this->testFileData),
|
||||
],
|
||||
],
|
||||
'status' => [
|
||||
[
|
||||
'value' => FALSE,
|
||||
],
|
||||
],
|
||||
'created' => [
|
||||
$this->formatExpectedTimestampItemValues($file->getCreatedTime()),
|
||||
],
|
||||
'changed' => [
|
||||
$this->formatExpectedTimestampItemValues($file->getChangedTime()),
|
||||
],
|
||||
];
|
||||
|
||||
return $expected_normalization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a file upload request. Wraps the Guzzle HTTP client.
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*
|
||||
* @param \Drupal\Core\Url $url
|
||||
* URL to request.
|
||||
* @param string $file_contents
|
||||
* The file contents to send as the request body.
|
||||
* @param array $headers
|
||||
* Additional headers to send with the request. Defaults will be added for
|
||||
* Content-Type and Content-Disposition.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
protected function fileRequest(Url $url, $file_contents, array $headers = []) {
|
||||
// Set the format for the response.
|
||||
$url->setOption('query', ['_format' => static::$format]);
|
||||
|
||||
$request_options = [];
|
||||
$request_options[RequestOptions::HEADERS] = $headers + [
|
||||
// Set the required (and only accepted) content type for the request.
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
// Set the required Content-Disposition header for the file name.
|
||||
'Content-Disposition' => 'file; filename="example.txt"',
|
||||
];
|
||||
$request_options[RequestOptions::BODY] = $file_contents;
|
||||
$request_options = NestedArray::mergeDeep($request_options, $this->getAuthenticationRequestOptions('POST'));
|
||||
|
||||
return $this->request('POST', $url, $request_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$this->grantPermissionsToTestedRole(['view test entity']);
|
||||
break;
|
||||
case 'POST':
|
||||
$this->grantPermissionsToTestedRole(['create entity_test entity_test_with_bundle entities', 'access content']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts expected normalized data matches response data.
|
||||
*
|
||||
* @param array $expected
|
||||
* The expected data.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* The file upload response.
|
||||
*/
|
||||
protected function assertResponseData(array $expected, ResponseInterface $response) {
|
||||
static::recursiveKSort($expected);
|
||||
$actual = $this->serializer->decode((string) $response->getBody(), static::$format);
|
||||
static::recursiveKSort($actual);
|
||||
|
||||
$this->assertSame($expected, $actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessCacheability() {
|
||||
// There is cacheability metadata to check as file uploads only allows POST
|
||||
// requests, which will not return cacheable responses.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RestResourceConfigHalJsonAnonTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RestResourceConfigHalJsonBasicAuthTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal', 'basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\Rest\RestResourceConfigResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class RestResourceConfigHalJsonCookieTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
160
2017/web/core/modules/rest/tests/src/Functional/ResourceTest.php
Normal file
160
2017/web/core/modules/rest/tests/src/Functional/ResourceTest.php
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\entity_test\Entity\EntityTest;
|
||||
use Drupal\rest\Entity\RestResourceConfig;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
/**
|
||||
* Tests the structure of a REST resource.
|
||||
*
|
||||
* @group rest
|
||||
*/
|
||||
class ResourceTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['hal', 'rest', 'entity_test', 'rest_test'];
|
||||
|
||||
/**
|
||||
* The entity.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create an entity programmatic.
|
||||
$this->entity = EntityTest::create([
|
||||
'name' => $this->randomMachineName(),
|
||||
'user_id' => 1,
|
||||
'field_test_text' => [
|
||||
0 => [
|
||||
'value' => $this->randomString(),
|
||||
'format' => 'plain_text',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->entity->save();
|
||||
|
||||
Role::load(AccountInterface::ANONYMOUS_ROLE)
|
||||
->grantPermission('view test entity')
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a resource without formats cannot be enabled.
|
||||
*/
|
||||
public function testFormats() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'entity.entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_auth' => [
|
||||
'basic_auth',
|
||||
],
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
// Verify that accessing the resource returns 406.
|
||||
$this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
|
||||
// \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
|
||||
// non-REST route a match, but a lower quality one: no format restrictions
|
||||
// means there's always a match and hence when there is no matching REST
|
||||
// route, the non-REST route is used, but can't render into
|
||||
// application/hal+json, so it returns a 406.
|
||||
$this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a resource without authentication cannot be enabled.
|
||||
*/
|
||||
public function testAuthentication() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'entity.entity_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'GET' => [
|
||||
'supported_formats' => [
|
||||
'hal_json',
|
||||
],
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
|
||||
// Verify that accessing the resource returns 401.
|
||||
$this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
|
||||
// \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
|
||||
// non-REST route a match, but a lower quality one: no format restrictions
|
||||
// means there's always a match and hence when there is no matching REST
|
||||
// route, the non-REST route is used, but can't render into
|
||||
// application/hal+json, so it returns a 406.
|
||||
$this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that serialization_class is optional.
|
||||
*/
|
||||
public function testSerializationClassIsOptional() {
|
||||
RestResourceConfig::create([
|
||||
'id' => 'serialization_test',
|
||||
'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
|
||||
'configuration' => [
|
||||
'POST' => [
|
||||
'supported_formats' => [
|
||||
'json',
|
||||
],
|
||||
'supported_auth' => [
|
||||
'cookie',
|
||||
],
|
||||
],
|
||||
],
|
||||
])->save();
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
|
||||
Role::load(RoleInterface::ANONYMOUS_ID)
|
||||
->grantPermission('restful post serialization_test')
|
||||
->save();
|
||||
|
||||
$serialized = $this->container->get('serializer')->serialize(['foo', 'bar'], 'json');
|
||||
$request_options = [
|
||||
RequestOptions::HEADERS => ['Content-Type' => 'application/json'],
|
||||
RequestOptions::BODY => $serialized,
|
||||
];
|
||||
/** @var \GuzzleHttp\ClientInterface $client */
|
||||
$client = $this->getSession()->getDriver()->getClient()->getClient();
|
||||
$response = $client->request('POST', $this->buildUrl('serialization_test', ['query' => ['_format' => 'json']]), $request_options);
|
||||
$this->assertSame(200, $response->getStatusCode());
|
||||
$this->assertSame('["foo","bar"]', (string) $response->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that resource URI paths are formatted properly.
|
||||
*/
|
||||
public function testUriPaths() {
|
||||
/** @var \Drupal\rest\Plugin\Type\ResourcePluginManager $manager */
|
||||
$manager = \Drupal::service('plugin.manager.rest');
|
||||
|
||||
foreach ($manager->getDefinitions() as $resource => $definition) {
|
||||
foreach ($definition['uri_paths'] as $key => $uri_path) {
|
||||
$this->assertFalse(strpos($uri_path, '//'), 'The resource URI path does not have duplicate slashes.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,505 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional;
|
||||
|
||||
use Behat\Mink\Driver\BrowserKitDriver;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\rest\RestResourceConfigInterface;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Subclass this for every REST resource, every format and every auth provider.
|
||||
*
|
||||
* For more guidance see
|
||||
* \Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase
|
||||
* which has recommendations for testing the
|
||||
* \Drupal\rest\Plugin\rest\resource\EntityResource REST resource for every
|
||||
* format and every auth provider. It's a special case (because that single REST
|
||||
* resource generates supports not just one thing, but many things — multiple
|
||||
* entity types), but the same principles apply.
|
||||
*/
|
||||
abstract class ResourceTestBase extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* The format to use in this test.
|
||||
*
|
||||
* A format is the combination of a certain normalizer and a certain
|
||||
* serializer.
|
||||
*
|
||||
* @see https://www.drupal.org/developing/api/8/serialization
|
||||
*
|
||||
* (The default is 'json' because that doesn't depend on any module.)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* The MIME type that corresponds to $format.
|
||||
*
|
||||
* (Sadly this cannot be computed automatically yet.)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* The authentication mechanism to use in this test.
|
||||
*
|
||||
* (The default is 'cookie' because that doesn't depend on any module.)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $auth = FALSE;
|
||||
|
||||
/**
|
||||
* The REST Resource Config entity ID under test (i.e. a resource type).
|
||||
*
|
||||
* The REST Resource plugin ID can be calculated from this.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @see \Drupal\rest\Entity\RestResourceConfig::__construct()
|
||||
*/
|
||||
protected static $resourceConfigId = NULL;
|
||||
|
||||
/**
|
||||
* The account to use for authentication, if any.
|
||||
*
|
||||
* @var null|\Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account = NULL;
|
||||
|
||||
/**
|
||||
* The REST resource config entity storage.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityStorageInterface
|
||||
*/
|
||||
protected $resourceConfigStorage;
|
||||
|
||||
/**
|
||||
* The serializer service.
|
||||
*
|
||||
* @var \Symfony\Component\Serializer\Serializer
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['rest'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->serializer = $this->container->get('serializer');
|
||||
|
||||
// Ensure the anonymous user role has no permissions at all.
|
||||
$user_role = Role::load(RoleInterface::ANONYMOUS_ID);
|
||||
foreach ($user_role->getPermissions() as $permission) {
|
||||
$user_role->revokePermission($permission);
|
||||
}
|
||||
$user_role->save();
|
||||
assert([] === $user_role->getPermissions(), 'The anonymous user role has no permissions at all.');
|
||||
|
||||
if (static::$auth !== FALSE) {
|
||||
// Ensure the authenticated user role has no permissions at all.
|
||||
$user_role = Role::load(RoleInterface::AUTHENTICATED_ID);
|
||||
foreach ($user_role->getPermissions() as $permission) {
|
||||
$user_role->revokePermission($permission);
|
||||
}
|
||||
$user_role->save();
|
||||
assert([] === $user_role->getPermissions(), 'The authenticated user role has no permissions at all.');
|
||||
|
||||
// Create an account.
|
||||
$this->account = $this->createUser();
|
||||
}
|
||||
else {
|
||||
// Otherwise, also create an account, so that any test involving User
|
||||
// entities will have the same user IDs regardless of authentication.
|
||||
$this->createUser();
|
||||
}
|
||||
|
||||
$this->resourceConfigStorage = $this->container->get('entity_type.manager')->getStorage('rest_resource_config');
|
||||
|
||||
// Ensure there's a clean slate: delete all REST resource config entities.
|
||||
$this->resourceConfigStorage->delete($this->resourceConfigStorage->loadMultiple());
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provisions the REST resource under test.
|
||||
*
|
||||
* @param string[] $formats
|
||||
* The allowed formats for this resource.
|
||||
* @param string[] $authentication
|
||||
* The allowed authentication providers for this resource.
|
||||
*/
|
||||
protected function provisionResource($formats = [], $authentication = [], array $methods = ['GET', 'POST', 'PATCH', 'DELETE']) {
|
||||
$this->resourceConfigStorage->create([
|
||||
'id' => static::$resourceConfigId,
|
||||
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
|
||||
'configuration' => [
|
||||
'methods' => $methods,
|
||||
'formats' => $formats,
|
||||
'authentication' => $authentication,
|
||||
],
|
||||
'status' => TRUE,
|
||||
])->save();
|
||||
$this->refreshTestStateAfterRestConfigChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the state of the tester to be in sync with the testee.
|
||||
*
|
||||
* Should be called after every change made to:
|
||||
* - RestResourceConfig entities
|
||||
* - the 'rest.settings' simple configuration
|
||||
*/
|
||||
protected function refreshTestStateAfterRestConfigChange() {
|
||||
// Ensure that the cache tags invalidator has its internal values reset.
|
||||
// Otherwise the http_response cache tag invalidation won't work.
|
||||
$this->refreshVariables();
|
||||
|
||||
// Tests using this base class may trigger route rebuilds due to changes to
|
||||
// RestResourceConfig entities or 'rest.settings'. Ensure the test generates
|
||||
// routes using an up-to-date router.
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expected error message.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method (GET, POST, PATCH, DELETE).
|
||||
*
|
||||
* @return string
|
||||
* The error string.
|
||||
*/
|
||||
protected function getExpectedUnauthorizedAccessMessage($method) {
|
||||
$resource_plugin_id = str_replace('.', ':', static::$resourceConfigId);
|
||||
$permission = 'restful ' . strtolower($method) . ' ' . $resource_plugin_id;
|
||||
return "The '$permission' permission is required.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the necessary authorization.
|
||||
*
|
||||
* In case of a test verifying publicly accessible REST resources: grant
|
||||
* permissions to the anonymous user role.
|
||||
*
|
||||
* In case of a test verifying behavior when using a particular authentication
|
||||
* provider: create a user with a particular set of permissions.
|
||||
*
|
||||
* Because of the $method parameter, it's possible to first set up
|
||||
* authentication for only GET, then add POST, et cetera. This then also
|
||||
* allows for verifying a 403 in case of missing authorization.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method for which to set up authentication.
|
||||
*
|
||||
* @see ::grantPermissionsToAnonymousRole()
|
||||
* @see ::grantPermissionsToAuthenticatedRole()
|
||||
*/
|
||||
abstract protected function setUpAuthorization($method);
|
||||
|
||||
/**
|
||||
* Verifies the error response in case of missing authentication.
|
||||
*
|
||||
* @param string $method
|
||||
* HTTP method.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* The response to assert.
|
||||
*/
|
||||
abstract protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response);
|
||||
|
||||
/**
|
||||
* Asserts normalization-specific edge cases.
|
||||
*
|
||||
* (Should be called before sending a well-formed request.)
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*
|
||||
* @param string $method
|
||||
* HTTP method.
|
||||
* @param \Drupal\Core\Url $url
|
||||
* URL to request.
|
||||
* @param array $request_options
|
||||
* Request options to apply.
|
||||
*/
|
||||
abstract protected function assertNormalizationEdgeCases($method, Url $url, array $request_options);
|
||||
|
||||
/**
|
||||
* Asserts authentication provider-specific edge cases.
|
||||
*
|
||||
* (Should be called before sending a well-formed request.)
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*
|
||||
* @param string $method
|
||||
* HTTP method.
|
||||
* @param \Drupal\Core\Url $url
|
||||
* URL to request.
|
||||
* @param array $request_options
|
||||
* Request options to apply.
|
||||
*/
|
||||
abstract protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options);
|
||||
|
||||
/**
|
||||
* Returns the expected cacheability of an unauthorized access response.
|
||||
*
|
||||
* @return \Drupal\Core\Cache\RefinableCacheableDependencyInterface
|
||||
* The expected cacheability.
|
||||
*/
|
||||
abstract protected function getExpectedUnauthorizedAccessCacheability();
|
||||
|
||||
/**
|
||||
* Initializes authentication.
|
||||
*
|
||||
* E.g. for cookie authentication, we first need to get a cookie.
|
||||
*/
|
||||
protected function initAuthentication() {}
|
||||
|
||||
/**
|
||||
* Returns Guzzle request options for authentication.
|
||||
*
|
||||
* @param string $method
|
||||
* The HTTP method for this authenticated request.
|
||||
*
|
||||
* @return array
|
||||
* Guzzle request options to use for authentication.
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*/
|
||||
protected function getAuthenticationRequestOptions($method) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants permissions to the anonymous role.
|
||||
*
|
||||
* @param string[] $permissions
|
||||
* Permissions to grant.
|
||||
*/
|
||||
protected function grantPermissionsToAnonymousRole(array $permissions) {
|
||||
$this->grantPermissions(Role::load(RoleInterface::ANONYMOUS_ID), $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants permissions to the authenticated role.
|
||||
*
|
||||
* @param string[] $permissions
|
||||
* Permissions to grant.
|
||||
*/
|
||||
protected function grantPermissionsToAuthenticatedRole(array $permissions) {
|
||||
$this->grantPermissions(Role::load(RoleInterface::AUTHENTICATED_ID), $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants permissions to the tested role: anonymous or authenticated.
|
||||
*
|
||||
* @param string[] $permissions
|
||||
* Permissions to grant.
|
||||
*
|
||||
* @see ::grantPermissionsToAuthenticatedRole()
|
||||
* @see ::grantPermissionsToAnonymousRole()
|
||||
*/
|
||||
protected function grantPermissionsToTestedRole(array $permissions) {
|
||||
if (static::$auth) {
|
||||
$this->grantPermissionsToAuthenticatedRole($permissions);
|
||||
}
|
||||
else {
|
||||
$this->grantPermissionsToAnonymousRole($permissions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a HTTP request. Wraps the Guzzle HTTP client.
|
||||
*
|
||||
* Why wrap the Guzzle HTTP client? Because we want to keep the actual test
|
||||
* code as simple as possible, and hence not require them to specify the
|
||||
* 'http_errors = FALSE' request option, nor do we want them to have to
|
||||
* convert Drupal Url objects to strings.
|
||||
*
|
||||
* We also don't want to follow redirects automatically, to ensure these tests
|
||||
* are able to detect when redirects are added or removed.
|
||||
*
|
||||
* @see \GuzzleHttp\ClientInterface::request()
|
||||
*
|
||||
* @param string $method
|
||||
* HTTP method.
|
||||
* @param \Drupal\Core\Url $url
|
||||
* URL to request.
|
||||
* @param array $request_options
|
||||
* Request options to apply.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
protected function request($method, Url $url, array $request_options) {
|
||||
$request_options[RequestOptions::HTTP_ERRORS] = FALSE;
|
||||
$request_options[RequestOptions::ALLOW_REDIRECTS] = FALSE;
|
||||
$request_options = $this->decorateWithXdebugCookie($request_options);
|
||||
$client = $this->getHttpClient();
|
||||
return $client->request($method, $url->setAbsolute(TRUE)->toString(), $request_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a resource response has the given status code and body.
|
||||
*
|
||||
* @param int $expected_status_code
|
||||
* The expected response status.
|
||||
* @param string|false $expected_body
|
||||
* The expected response body. FALSE in case this should not be asserted.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* The response to assert.
|
||||
* @param string[]|false $expected_cache_tags
|
||||
* (optional) The expected cache tags in the X-Drupal-Cache-Tags response
|
||||
* header, or FALSE if that header should be absent. Defaults to FALSE.
|
||||
* @param string[]|false $expected_cache_contexts
|
||||
* (optional) The expected cache contexts in the X-Drupal-Cache-Contexts
|
||||
* response header, or FALSE if that header should be absent. Defaults to
|
||||
* FALSE.
|
||||
* @param string|false $expected_page_cache_header_value
|
||||
* (optional) The expected X-Drupal-Cache response header value, or FALSE if
|
||||
* that header should be absent. Possible strings: 'MISS', 'HIT'. Defaults
|
||||
* to FALSE.
|
||||
* @param string|false $expected_dynamic_page_cache_header_value
|
||||
* (optional) The expected X-Drupal-Dynamic-Cache response header value, or
|
||||
* FALSE if that header should be absent. Possible strings: 'MISS', 'HIT'.
|
||||
* Defaults to FALSE.
|
||||
*/
|
||||
protected function assertResourceResponse($expected_status_code, $expected_body, ResponseInterface $response, $expected_cache_tags = FALSE, $expected_cache_contexts = FALSE, $expected_page_cache_header_value = FALSE, $expected_dynamic_page_cache_header_value = FALSE) {
|
||||
$this->assertSame($expected_status_code, $response->getStatusCode());
|
||||
if ($expected_status_code === 204) {
|
||||
// DELETE responses should not include a Content-Type header. But Apache
|
||||
// sets it to 'text/html' by default. We also cannot detect the presence
|
||||
// of Apache either here in the CLI. For now having this documented here
|
||||
// is all we can do.
|
||||
// $this->assertSame(FALSE, $response->hasHeader('Content-Type'));
|
||||
$this->assertSame('', (string) $response->getBody());
|
||||
}
|
||||
else {
|
||||
$this->assertSame([static::$mimeType], $response->getHeader('Content-Type'));
|
||||
if ($expected_body !== FALSE) {
|
||||
$this->assertSame($expected_body, (string) $response->getBody());
|
||||
}
|
||||
}
|
||||
|
||||
// Expected cache tags: X-Drupal-Cache-Tags header.
|
||||
$this->assertSame($expected_cache_tags !== FALSE, $response->hasHeader('X-Drupal-Cache-Tags'));
|
||||
if (is_array($expected_cache_tags)) {
|
||||
$this->assertSame($expected_cache_tags, explode(' ', $response->getHeader('X-Drupal-Cache-Tags')[0]));
|
||||
}
|
||||
|
||||
// Expected cache contexts: X-Drupal-Cache-Contexts header.
|
||||
$this->assertSame($expected_cache_contexts !== FALSE, $response->hasHeader('X-Drupal-Cache-Contexts'));
|
||||
if (is_array($expected_cache_contexts)) {
|
||||
$this->assertSame($expected_cache_contexts, explode(' ', $response->getHeader('X-Drupal-Cache-Contexts')[0]));
|
||||
}
|
||||
|
||||
// Expected Page Cache header value: X-Drupal-Cache header.
|
||||
if ($expected_page_cache_header_value !== FALSE) {
|
||||
$this->assertTrue($response->hasHeader('X-Drupal-Cache'));
|
||||
$this->assertSame($expected_page_cache_header_value, $response->getHeader('X-Drupal-Cache')[0]);
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Cache'));
|
||||
}
|
||||
|
||||
// Expected Dynamic Page Cache header value: X-Drupal-Dynamic-Cache header.
|
||||
if ($expected_dynamic_page_cache_header_value !== FALSE) {
|
||||
$this->assertTrue($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
$this->assertSame($expected_dynamic_page_cache_header_value, $response->getHeader('X-Drupal-Dynamic-Cache')[0]);
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($response->hasHeader('X-Drupal-Dynamic-Cache'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a resource error response has the given message.
|
||||
*
|
||||
* @param int $expected_status_code
|
||||
* The expected response status.
|
||||
* @param string $expected_message
|
||||
* The expected error message.
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* The error response to assert.
|
||||
* @param string[]|false $expected_cache_tags
|
||||
* (optional) The expected cache tags in the X-Drupal-Cache-Tags response
|
||||
* header, or FALSE if that header should be absent. Defaults to FALSE.
|
||||
* @param string[]|false $expected_cache_contexts
|
||||
* (optional) The expected cache contexts in the X-Drupal-Cache-Contexts
|
||||
* response header, or FALSE if that header should be absent. Defaults to
|
||||
* FALSE.
|
||||
* @param string|false $expected_page_cache_header_value
|
||||
* (optional) The expected X-Drupal-Cache response header value, or FALSE if
|
||||
* that header should be absent. Possible strings: 'MISS', 'HIT'. Defaults
|
||||
* to FALSE.
|
||||
* @param string|false $expected_dynamic_page_cache_header_value
|
||||
* (optional) The expected X-Drupal-Dynamic-Cache response header value, or
|
||||
* FALSE if that header should be absent. Possible strings: 'MISS', 'HIT'.
|
||||
* Defaults to FALSE.
|
||||
*/
|
||||
protected function assertResourceErrorResponse($expected_status_code, $expected_message, ResponseInterface $response, $expected_cache_tags = FALSE, $expected_cache_contexts = FALSE, $expected_page_cache_header_value = FALSE, $expected_dynamic_page_cache_header_value = FALSE) {
|
||||
$expected_body = ($expected_message !== FALSE) ? $this->serializer->encode(['message' => $expected_message], static::$format) : FALSE;
|
||||
$this->assertResourceResponse($expected_status_code, $expected_body, $response, $expected_cache_tags, $expected_cache_contexts, $expected_page_cache_header_value, $expected_dynamic_page_cache_header_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Xdebug cookie to the request options.
|
||||
*
|
||||
* @param array $request_options
|
||||
* The request options.
|
||||
*
|
||||
* @return array
|
||||
* Request options updated with the Xdebug cookie if present.
|
||||
*/
|
||||
protected function decorateWithXdebugCookie(array $request_options) {
|
||||
$session = $this->getSession();
|
||||
$driver = $session->getDriver();
|
||||
if ($driver instanceof BrowserKitDriver) {
|
||||
$client = $driver->getClient();
|
||||
foreach ($client->getCookieJar()->all() as $cookie) {
|
||||
if (isset($request_options[RequestOptions::HEADERS]['Cookie'])) {
|
||||
$request_options[RequestOptions::HEADERS]['Cookie'] .= '; ' . $cookie->getName() . '=' . $cookie->getValue();
|
||||
}
|
||||
else {
|
||||
$request_options[RequestOptions::HEADERS]['Cookie'] = $cookie->getName() . '=' . $cookie->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $request_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sorts an array by key.
|
||||
*
|
||||
* @param array $array
|
||||
* An array to sort.
|
||||
*
|
||||
* @return array
|
||||
* The sorted array.
|
||||
*/
|
||||
protected static function recursiveKSort(array &$array) {
|
||||
// First, sort the main array.
|
||||
ksort($array);
|
||||
|
||||
// Then check for child arrays.
|
||||
foreach ($array as $key => &$value) {
|
||||
if (is_array($value)) {
|
||||
static::recursiveKSort($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class RestResourceConfigJsonAnonTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class RestResourceConfigJsonBasicAuthTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\rest\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class RestResourceConfigJsonCookieTest extends RestResourceConfigResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue