View source
<?php
namespace Drupal\Tests\media\Functional\Rest;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\media\Entity\Media;
use Drupal\media\Entity\MediaType;
use Drupal\rest\RestResourceConfigInterface;
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
use GuzzleHttp\RequestOptions;
abstract class MediaResourceTestBase extends EntityResourceTestBase {
protected static $modules = [
'media',
];
protected static $entityTypeId = 'media';
protected $entity;
protected static $patchProtectedFieldNames = [
'changed' => NULL,
];
public function setUp() {
parent::setUp();
\Drupal::configFactory()
->getEditable('media.settings')
->set('standalone_url', TRUE)
->save(TRUE);
$this->resourceConfigStorage
->create([
'id' => 'entity.file',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => [
'GET',
],
'formats' => [
static::$format,
],
'authentication' => isset(static::$auth) ? [
static::$auth,
] : [],
],
'status' => TRUE,
])
->save();
$this->container
->get('router.builder')
->rebuild();
}
protected function setUpAuthorization($method) {
switch ($method) {
case 'GET':
$this
->grantPermissionsToTestedRole([
'view media',
]);
break;
case 'POST':
$this
->grantPermissionsToTestedRole([
'create camelids media',
'access content',
]);
break;
case 'PATCH':
$this
->grantPermissionsToTestedRole([
'edit any camelids media',
]);
$this
->grantPermissionsToTestedRole([
'access content',
]);
break;
case 'DELETE':
$this
->grantPermissionsToTestedRole([
'delete any camelids media',
]);
break;
}
}
protected function createEntity() {
if (!MediaType::load('camelids')) {
$media_type = MediaType::create([
'name' => 'Camelids',
'id' => 'camelids',
'description' => 'Camelids are large, strictly herbivorous animals with slender necks and long legs.',
'source' => 'file',
]);
$media_type
->save();
$source_field = $media_type
->getSource()
->createSourceField($media_type);
$source_field
->getFieldStorageDefinition()
->save();
$source_field
->save();
$media_type
->set('source_configuration', [
'source_field' => $source_field
->getName(),
])
->save();
}
$file = File::create([
'uri' => 'public://llama.txt',
]);
$file
->setPermanent();
$file
->save();
$media = Media::create([
'bundle' => 'camelids',
'field_media_file' => [
'target_id' => $file
->id(),
],
]);
$media
->setName('Llama')
->setPublished()
->setCreatedTime(123456789)
->setOwnerId(static::$auth ? $this->account
->id() : 0)
->setRevisionUserId(static::$auth ? $this->account
->id() : 0)
->save();
return $media;
}
protected function getExpectedNormalizedEntity() {
$file = File::load(1);
$thumbnail = File::load(2);
$author = User::load($this->entity
->getOwnerId());
return [
'mid' => [
[
'value' => 1,
],
],
'uuid' => [
[
'value' => $this->entity
->uuid(),
],
],
'vid' => [
[
'value' => 1,
],
],
'langcode' => [
[
'value' => 'en',
],
],
'bundle' => [
[
'target_id' => 'camelids',
'target_type' => 'media_type',
'target_uuid' => MediaType::load('camelids')
->uuid(),
],
],
'name' => [
[
'value' => 'Llama',
],
],
'field_media_file' => [
[
'description' => NULL,
'display' => NULL,
'target_id' => (int) $file
->id(),
'target_type' => 'file',
'target_uuid' => $file
->uuid(),
'url' => $file
->createFileUrl(FALSE),
],
],
'thumbnail' => [
[
'alt' => '',
'width' => 180,
'height' => 180,
'target_id' => (int) $thumbnail
->id(),
'target_type' => 'file',
'target_uuid' => $thumbnail
->uuid(),
'title' => NULL,
'url' => $thumbnail
->createFileUrl(FALSE),
],
],
'status' => [
[
'value' => TRUE,
],
],
'created' => [
[
'value' => (new \DateTime())
->setTimestamp(123456789)
->setTimezone(new \DateTimeZone('UTC'))
->format(\DateTime::RFC3339),
'format' => \DateTime::RFC3339,
],
],
'changed' => [
[
'value' => (new \DateTime())
->setTimestamp((int) $this->entity
->getChangedTime())
->setTimezone(new \DateTimeZone('UTC'))
->format(\DateTime::RFC3339),
'format' => \DateTime::RFC3339,
],
],
'revision_created' => [
[
'value' => (new \DateTime())
->setTimestamp((int) $this->entity
->getRevisionCreationTime())
->setTimezone(new \DateTimeZone('UTC'))
->format(\DateTime::RFC3339),
'format' => \DateTime::RFC3339,
],
],
'default_langcode' => [
[
'value' => TRUE,
],
],
'uid' => [
[
'target_id' => (int) $author
->id(),
'target_type' => 'user',
'target_uuid' => $author
->uuid(),
'url' => base_path() . 'user/' . $author
->id(),
],
],
'revision_user' => [
[
'target_id' => (int) $author
->id(),
'target_type' => 'user',
'target_uuid' => $author
->uuid(),
'url' => base_path() . 'user/' . $author
->id(),
],
],
'revision_log_message' => [],
'revision_translation_affected' => [
[
'value' => TRUE,
],
],
];
}
protected function getNormalizedPostEntity() {
return [
'bundle' => [
[
'target_id' => 'camelids',
],
],
'name' => [
[
'value' => 'Dramallama',
],
],
'field_media_file' => [
[
'description' => NULL,
'display' => NULL,
'target_id' => 3,
],
],
];
}
protected function getNormalizedPatchEntity() {
return array_diff_key($this
->getNormalizedPostEntity(), [
'field_media_file' => TRUE,
]);
}
protected function getExpectedUnauthorizedAccessMessage($method) {
switch ($method) {
case 'GET':
return "The 'view media' permission is required when the media item is published.";
case 'POST':
return "The following permissions are required: 'administer media' OR 'create media' OR 'create camelids media'.";
case 'PATCH':
return "The following permissions are required: 'update any media' OR 'update own media' OR 'camelids: edit any media' OR 'camelids: edit own media'.";
case 'DELETE':
return "The following permissions are required: 'delete any media' OR 'delete own media' OR 'camelids: delete any media' OR 'camelids: delete own media'.";
default:
return parent::getExpectedUnauthorizedAccessMessage($method);
}
}
public function testPost() {
$file_storage = $this->container
->get('entity_type.manager')
->getStorage('file');
$this
->uploadFile();
$file = $file_storage
->loadUnchanged(3);
$this
->assertTrue($file
->isTemporary());
$this
->assertFalse($file
->isPermanent());
parent::testPost();
$file = $file_storage
->loadUnchanged(3);
$this
->assertFalse($file
->isTemporary());
$this
->assertTrue($file
->isPermanent());
}
protected function uploadFile() {
$this->resourceConfigStorage
->create([
'id' => 'file.upload',
'granularity' => RestResourceConfigInterface::RESOURCE_GRANULARITY,
'configuration' => [
'methods' => [
'POST',
],
'formats' => [
static::$format,
],
'authentication' => isset(static::$auth) ? [
static::$auth,
] : [],
],
'status' => TRUE,
])
->save();
$this
->refreshTestStateAfterRestConfigChange();
$this
->initAuthentication();
$url = Url::fromUri('base:file/upload/media/camelids/field_media_file');
$url
->setOption('query', [
'_format' => static::$format,
]);
$request_options = [];
$request_options[RequestOptions::HEADERS] = [
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'file; filename="drupal rocks 🤘.txt"',
];
$request_options[RequestOptions::BODY] = 'Drupal is the best!';
$request_options = NestedArray::mergeDeep($request_options, $this
->getAuthenticationRequestOptions('POST'));
$response = $this
->request('POST', $url, $request_options);
$this
->assertResourceErrorResponse(403, $this
->getExpectedUnauthorizedAccessMessage('POST'), $response);
$this
->grantPermissionsToTestedRole([
'create camelids media',
]);
$response = $this
->request('POST', $url, $request_options);
$this
->assertSame(201, $response
->getStatusCode());
$expected = $this
->getExpectedNormalizedFileEntity();
static::recursiveKSort($expected);
$actual = $this->serializer
->decode((string) $response
->getBody(), static::$format);
static::recursiveKSort($actual);
$this
->assertSame($expected, $actual);
$role = Role::load(static::$auth ? RoleInterface::AUTHENTICATED_ID : RoleInterface::ANONYMOUS_ID);
$role
->revokePermission('create camelids media');
$role
->trustData()
->save();
}
protected function getExpectedNormalizedFileEntity() {
$file = File::load(3);
$owner = static::$auth ? $this->account : User::load(0);
return [
'fid' => [
[
'value' => 3,
],
],
'uuid' => [
[
'value' => $file
->uuid(),
],
],
'langcode' => [
[
'value' => 'en',
],
],
'uid' => [
[
'target_id' => (int) $owner
->id(),
'target_type' => 'user',
'target_uuid' => $owner
->uuid(),
'url' => base_path() . 'user/' . $owner
->id(),
],
],
'filename' => [
[
'value' => 'drupal rocks 🤘.txt',
],
],
'uri' => [
[
'value' => 'public://' . date('Y-m') . '/drupal rocks 🤘.txt',
'url' => base_path() . $this->siteDirectory . '/files/' . date('Y-m') . '/drupal%20rocks%20%F0%9F%A4%98.txt',
],
],
'filemime' => [
[
'value' => 'text/plain',
],
],
'filesize' => [
[
'value' => 19,
],
],
'status' => [
[
'value' => FALSE,
],
],
'created' => [
[
'value' => (new \DateTime())
->setTimestamp($file
->getCreatedTime())
->setTimezone(new \DateTimeZone('UTC'))
->format(\DateTime::RFC3339),
'format' => \DateTime::RFC3339,
],
],
'changed' => [
[
'value' => (new \DateTime())
->setTimestamp($file
->getChangedTime())
->setTimezone(new \DateTimeZone('UTC'))
->format(\DateTime::RFC3339),
'format' => \DateTime::RFC3339,
],
],
];
}
protected function getExpectedUnauthorizedEntityAccessCacheability($is_authenticated) {
return parent::getExpectedUnauthorizedEntityAccessCacheability($is_authenticated)
->addCacheTags([
'media:1',
]);
}
}