diff --git a/core/modules/file/src/FileAccessControlHandler.php b/core/modules/file/src/FileAccessControlHandler.php index 9b24f57..2de8978 100644 --- a/core/modules/file/src/FileAccessControlHandler.php +++ b/core/modules/file/src/FileAccessControlHandler.php @@ -48,7 +48,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter if ($operation == 'delete' || $operation == 'update') { $account = $this->prepareUser($account); $file_uid = $entity->get('uid')->getValue(); - // Only admin users and the file owner can delete the file entity. + // Only admin users and the file owner can delete and update the file entity. if ($account->hasPermission('administer nodes') || $account->id() == $file_uid[0]['target_id']) { return AccessResult::allowed(); } @@ -78,20 +78,13 @@ protected function getFileReferences(FileInterface $file) { /** * {@inheritdoc} */ - protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { - return AccessResult::allowed(); - } - - /** - * {@inheritdoc} - */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { // No user can edit the status of a file. Prevents saving a new file as // persistent before even validating it. - if ($field_definition->getName() == 'status' && $operation == 'edit') { + if ($field_definition->getName() === 'status' && $operation === 'edit') { return AccessResult::forbidden(); } - return AccessResult::allowed(); + return parent::checkFieldAccess($operation, $field_definition, $account, $items); } } diff --git a/core/modules/hal/hal.services.yml b/core/modules/hal/hal.services.yml index 58cc6cd..80cce6d 100644 --- a/core/modules/hal/hal.services.yml +++ b/core/modules/hal/hal.services.yml @@ -16,7 +16,7 @@ services: class: Drupal\hal\Normalizer\FileEntityNormalizer tags: - { name: normalizer, priority: 20 } - arguments: ['@rest.link_manager', '@entity.manager', '@module_handler', '@file_system'] + arguments: ['@entity.manager', '@rest.link_manager', '@module_handler', '@file_system'] serializer.normalizer.entity.hal: class: Drupal\hal\Normalizer\ContentEntityNormalizer arguments: ['@rest.link_manager', '@entity.manager', '@module_handler'] diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php index 9ed07af..2818f55 100644 --- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php +++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php @@ -143,6 +143,8 @@ public function denormalize($data, $class, $format = NULL, array $context = arra if ($entity_type->hasKey('bundle')) { $bundle_key = $entity_type->getKey('bundle'); $values[$bundle_key] = $typed_data_ids['bundle']; + // Unset the bundle key from data, if it's there. + unset($data[$bundle_key]); } // Create the entity. diff --git a/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php b/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php index f39bab6..7017575 100644 --- a/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php +++ b/core/modules/hal/src/Normalizer/EntityReferenceItemNormalizer.php @@ -82,6 +82,8 @@ public function normalize($field_item, $format = NULL, array $context = array()) if ($langcode) { $embedded['lang'] = $link['lang'] = $langcode; } + // Merge in the properties of the parent implementation. + $embedded += $properties[$field_name][0]; // The returned structure will be recursively merged into the normalized // entity so that the items are properly added to the _links and _embedded @@ -92,7 +94,7 @@ public function normalize($field_item, $format = NULL, array $context = array()) $field_uri => array($link), ), '_embedded' => array( - $field_uri => array($embedded + $properties[$field_name][0]), + $field_uri => array($embedded), ), ); } @@ -101,7 +103,7 @@ public function normalize($field_item, $format = NULL, array $context = array()) * {@inheritdoc} */ protected function constructValue($data, $context) { - /** @var FieldItemInterface $field_item */ + /** @var \Drupal\Core\Field\FieldItemInterface $field_item */ $field_item = $context['target_instance']; $field_definition = $field_item->getFieldDefinition(); $target_type = $field_definition->getSetting('target_type'); @@ -109,7 +111,7 @@ protected function constructValue($data, $context) { if (isset($id)) { $constructed = array('target_id' => $id); foreach ($field_item->getProperties() as $property => $value) { - if ($property != 'target_id' && array_key_exists($property, $data)) { + if ($property !== 'target_id' && isset($data[$property])) { $constructed[$property] = $data[$property]; } } @@ -137,7 +139,7 @@ public function getUuid($data) { * * The relation URI is used as a property key when building the HAL structure. * - * @param FieldItemInterface $field_item + * @param \Drupal\Core\Field\FieldItemInterface $field_item * The field item that is being normalized. * * @return string diff --git a/core/modules/hal/src/Normalizer/FileEntityNormalizer.php b/core/modules/hal/src/Normalizer/FileEntityNormalizer.php index f26e9e0..2abdbf8 100644 --- a/core/modules/hal/src/Normalizer/FileEntityNormalizer.php +++ b/core/modules/hal/src/Normalizer/FileEntityNormalizer.php @@ -14,6 +14,11 @@ class FileEntityNormalizer extends ContentEntityNormalizer { /** + * Key used to store actual file data. + */ + const FILE_DATA_KEY = 'data'; + + /** * The interface or class that this Normalizer supports. * * @var string @@ -26,34 +31,32 @@ class FileEntityNormalizer extends ContentEntityNormalizer { protected $fileSystem; /** - * Constructs an FileEntityNormalizer object. + * Constructs a FileEntityNormalizer object. * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. + * @param \Drupal\rest\LinkManager\LinkManagerInterface $link_manager + * The hypermedia link manager. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system. */ - public function __construct(LinkManagerInterface $link_manager, EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, FileSystemInterface $file_system) { - $this->fileSystem = $file_system; + public function __construct(EntityManagerInterface $entity_manager, LinkManagerInterface $link_manager, ModuleHandlerInterface $module_handler, FileSystemInterface $file_system) { parent::__construct($link_manager, $entity_manager, $module_handler); - } - - /** - * {@inheritdoc} - */ - public function normalize($entity, $format = NULL, array $context = array()) { - $data = parent::normalize($entity, $format, $context); - - return $data; + $this->fileSystem = $file_system; } /** * {@inheritdoc} */ public function denormalize($data, $class, $format = NULL, array $context = array()) { - // File content can be passed base64 encoded in a special "data" property. + // File content can be passed base64 encoded in a special "data" property + // under the field data. // That property is not a field, so we remove it before denormalizing the // rest of the file entity. - $file_data = $data['data'][0]['value']; - unset($data['data']); + $file_data = $data[self::FILE_DATA_KEY][0]['value']; + unset($data[self::FILE_DATA_KEY]); $entity = parent::denormalize($data, $class, $format, $context); @@ -61,8 +64,9 @@ public function denormalize($data, $class, $format = NULL, array $context = arra if (!isset($context['request_method']) || $context['request_method'] != 'patch') { $file_contents = base64_decode($file_data); $dirname = $this->fileSystem->dirname($entity->getFileUri()); + file_prepare_directory($dirname, FILE_CREATE_DIRECTORY); - if ($uri = file_unmanaged_save_data($file_contents, file_build_uri(drupal_basename($entity->getFilename())))) { + if ($uri = file_unmanaged_save_data($file_contents, file_build_uri($this->fileSystem->basename($entity->getFilename())))) { $entity->setFileUri($uri); } else { diff --git a/core/modules/hal/src/Tests/FileDenormalizeTest.php b/core/modules/hal/src/Tests/FileDenormalizeTest.php index ad5568e..f766d7d 100644 --- a/core/modules/hal/src/Tests/FileDenormalizeTest.php +++ b/core/modules/hal/src/Tests/FileDenormalizeTest.php @@ -3,6 +3,7 @@ namespace Drupal\hal\Tests; use Drupal\file\Entity\File; +use Drupal\hal\Normalizer\FileEntityNormalizer; use Drupal\simpletest\WebTestBase; /** @@ -34,13 +35,12 @@ public function testFileDenormalize() { $file = File::create($file_params); file_put_contents($file->getFileUri(), 'hello world'); $file->save(); - $data = file_get_contents($file_params['uri']); - $data = base64_encode($data); + $data = base64_encode(file_get_contents($file_params['uri'])); $serializer = \Drupal::service('serializer'); $normalized_data = $serializer->normalize($file, 'hal_json'); // Adding data to the entity. - $normalized_data['data'][0]['value'] = $data; + $normalized_data[FileEntityNormalizer::FILE_DATA_KEY][0]['value'] = $data; // Use 'patch' to avoid trying to recreate the file. $denormalized = $serializer->denormalize($normalized_data, File::class, 'hal_json', array('request_method' => 'patch')); $this->assertTrue($denormalized instanceof File, 'A File instance was created.'); diff --git a/core/modules/hal/tests/src/Kernel/EntityNormalizeTest.php b/core/modules/hal/tests/src/Kernel/EntityNormalizeTest.php index 23eb2ff..6f8632e 100644 --- a/core/modules/hal/tests/src/Kernel/EntityNormalizeTest.php +++ b/core/modules/hal/tests/src/Kernel/EntityNormalizeTest.php @@ -4,6 +4,7 @@ use Drupal\comment\Tests\CommentTestTrait; use Drupal\comment\Entity\Comment; +use Drupal\hal\Normalizer\FileEntityNormalizer; use Drupal\node\Entity\Node; use Drupal\user\Entity\User; use Drupal\node\Entity\NodeType; @@ -231,7 +232,7 @@ public function testFile() { $normalized = $this->serializer->normalize($file, $this->format); // Adding data to the entity. - $normalized['data'][0]['value'] = $data; + $normalized[FileEntityNormalizer::FILE_DATA_KEY][0]['value'] = $data; // Use PATCH to avoid trying to create new file on denormalize. $denormalized_file = $this->serializer->denormalize($normalized, File::class, $this->format, ['request_method' => 'patch']); diff --git a/core/modules/hal/tests/src/Kernel/FileFieldNormalizeTest.php b/core/modules/hal/tests/src/Kernel/FileFieldNormalizeTest.php index 06dff16..4a54913 100644 --- a/core/modules/hal/tests/src/Kernel/FileFieldNormalizeTest.php +++ b/core/modules/hal/tests/src/Kernel/FileFieldNormalizeTest.php @@ -36,10 +36,9 @@ public function setUp() { } /** - * Tests that file field is identical before and after de/serialization. + * Tests that file field is identical before and after (de)serialization. */ public function testFileFieldNormalize() { - // Create a file. $file_name = 'test_file_field_normalize.txt'; file_put_contents("public://$file_name", 'hello world'); $file = File::create([ @@ -77,7 +76,6 @@ public function testFileFieldNormalize() { * Tests that image field is identical before and after de/serialization. */ public function testImageFieldNormalize() { - // Create a file. $file_name = $this->randomMachineName() . '.png'; file_put_contents("public://$file_name", $this->randomString()); $file = File::create([ diff --git a/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php b/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php index a9cc6e0..1a1f08e 100644 --- a/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php +++ b/core/modules/hal/tests/src/Kernel/NormalizerTestBase.php @@ -138,7 +138,7 @@ protected function setUp() { // Set up the mock serializer. $normalizers = array( new FileEntityNormalizer($link_manager, $this->container->get('entity.manager'), $this->container->get('module_handler'), $this->container->get('file_system')), - new ContentEntityNormalizer($link_manager, $this->container->get('entity.manager'), $this->container->get('module_handler')), new EntityReferenceItemNormalizer($link_manager, $chain_resolver), + new ContentEntityNormalizer($link_manager, $this->container->get('entity.manager'), $this->container->get('module_handler')), new EntityReferenceItemNormalizer($link_manager, $chain_resolver), new FieldItemNormalizer(), new FieldNormalizer(), ); diff --git a/core/modules/rest/src/Tests/FileTest.php b/core/modules/rest/src/Tests/FileTest.php index 705de75..79f407c 100644 --- a/core/modules/rest/src/Tests/FileTest.php +++ b/core/modules/rest/src/Tests/FileTest.php @@ -67,7 +67,7 @@ public function testCrudFile() { $normalized_data = $this->serializer->normalize($file, 'hal_json'); $normalized_data['data'][0]['value'] = $data; - // Remove non-accessible fields. + // Remove non-modifiable fields. unset($normalized_data['status']); unset($normalized_data['changed']);