Skip to content
Snippets Groups Projects
Verified Commit ec8a42f8 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3437068 by phenaproxima: When importing file entities, check for duplicate files

(cherry picked from commit 67ac9bc2f75f3f284427a00208aa0c019c8e6459)
parent 3b3be1d0
No related branches found
No related tags found
1 merge request!7908Recipes API on 10.3.x
......@@ -87,29 +87,45 @@ public function importContent(Finder $content): void {
// If a file exists in the same folder, copy it to the designated
// target URI.
if ($entity instanceof FileInterface) {
/** @var string $uri */
$uri = $entity->getFileUri();
$file_source = $path . '/' . $entity->getFilename();
if (file_exists($file_source)) {
$target_directory = dirname($uri);
$this->fileSystem->prepareDirectory($target_directory, FileSystemInterface::CREATE_DIRECTORY);
// @todo https://drupal.org/i/3437068 Don't copy the file if it
// already exists.
$new_uri = $this->fileSystem->copy($file_source, $uri);
$entity->setFileUri($new_uri);
}
else {
$this->logger?->warning("File entity %name was imported, but the associated file (@path) was not found.", [
'%name' => $entity->getFilename(),
'@path' => $file_source,
]);
}
$this->copyFileAssociatedWithEntity($path, $entity);
}
$entity->save();
}
$this->accountSwitcher->switchBack();
}
private function copyFileAssociatedWithEntity(string $path, FileInterface $entity): void {
$destination = $entity->getFileUri();
assert(is_string($destination));
// If the source file doesn't exist, there's nothing we can do.
$source = $path . '/' . basename($destination);
if (!file_exists($source)) {
$this->logger?->warning("File entity %name was imported, but the associated file (@path) was not found.", [
'%name' => $entity->label(),
'@path' => $source,
]);
return;
}
if (file_exists($destination)) {
$source_hash = hash_file('sha256', $source);
assert(is_string($source_hash));
$destination_hash = hash_file('sha256', $destination);
assert(is_string($destination_hash));
// If we already have the file, we don't need to do anything else.
if (hash_equals($source_hash, $destination_hash)) {
return;
}
}
$target_directory = dirname($destination);
$this->fileSystem->prepareDirectory($target_directory, FileSystemInterface::CREATE_DIRECTORY);
$uri = $this->fileSystem->copy($source, $destination);
$entity->setFileUri($uri);
}
/**
* Converts an array of content entity data to a content entity object.
*
......
......@@ -163,6 +163,21 @@ private function assertContentWasImported(): void {
$this->assertSame('druplicon.png', $file->getFilename());
$this->assertSame('d8404562-efcc-40e3-869e-40132d53fe0b', $file->uuid());
// Another file entity referencing an existing file should have the same
// file URI -- in other words, it should have reused the existing file.
$duplicate_file = $entity_repository->loadEntityByUuid('file', '23a7f61f-1db3-407d-a6dd-eb4731995c9f');
$this->assertInstanceOf(FileInterface::class, $duplicate_file);
$this->assertSame('druplicon-duplicate.png', $duplicate_file->getFilename());
$this->assertSame($file->getFileUri(), $duplicate_file->getFileUri());
// Another file entity that references a file with the same name as, but
// different contents than, an existing file, should be imported and the
// file should be renamed.
$different_file = $entity_repository->loadEntityByUuid('file', 'a6b79928-838f-44bd-a8f0-44c2fff9e4cc');
$this->assertInstanceOf(FileInterface::class, $different_file);
$this->assertSame('druplicon-different.png', $different_file->getFilename());
$this->assertStringEndsWith('/druplicon_0.png', (string) $different_file->getFileUri());
// Our node should have a menu link, and it should use the path alias we
// included with the recipe.
$menu_link = $entity_repository->loadEntityByUuid('menu_link_content', '3434bd5a-d2cd-4f26-bf79-a7f6b951a21b');
......
_meta:
version: '1.0'
entity_type: file
uuid: a6b79928-838f-44bd-a8f0-44c2fff9e4cc
default_langcode: en
default:
uid:
-
target_id: 1
filename:
-
value: druplicon-different.png
uri:
-
value: 'public://2024-03/druplicon.png'
filemime:
-
value: text/plain
filesize:
-
value: 11
status:
-
value: true
created:
-
value: 1711121742
Not a PNG.
_meta:
version: '1.0'
entity_type: file
uuid: 23a7f61f-1db3-407d-a6dd-eb4731995c9f
default_langcode: en
default:
uid:
-
target_id: 1
filename:
-
value: druplicon-duplicate.png
uri:
-
value: 'public://2024-03/druplicon.png'
filemime:
-
value: image/png
filesize:
-
value: 3905
status:
-
value: true
created:
-
value: 1711121742
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment