Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions migrations/Version20250220215048.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use App\Migration\AbstractMultiPlatformMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250220215048 extends AbstractMultiPlatformMigration
{
public function getDescription(): string
{
return 'Split $path property for attachments into $internal_path and $external_path';
}

public function mySQLUp(Schema $schema): void
{
//Create the new columns as nullable (that is easier modifying them)
$this->addSql('ALTER TABLE attachments ADD internal_path VARCHAR(255) DEFAULT NULL, ADD external_path VARCHAR(255) DEFAULT NULL');

//Copy the data from path to external_path and remove the path column
$this->addSql('UPDATE attachments SET external_path=path');
$this->addSql('ALTER TABLE attachments DROP path');


$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%MEDIA#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%BASE#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%SECURE#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS3D#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET external_path=NULL WHERE internal_path IS NOT NULL');
}

public function mySQLDown(Schema $schema): void
{
$this->addSql('UPDATE attachments SET external_path=internal_path WHERE internal_path IS NOT NULL');
$this->addSql('ALTER TABLE attachments DROP internal_path');
$this->addSql('ALTER TABLE attachments RENAME COLUMN external_path TO path');
}

public function postgreSQLUp(Schema $schema): void
{
//We can use the same SQL for PostgreSQL as for MySQL
$this->mySQLUp($schema);
}

public function postgreSQLDown(Schema $schema): void
{
//We can use the same SQL for PostgreSQL as for MySQL
$this->mySQLDown($schema);
}

public function sqLiteUp(Schema $schema): void
{
$this->addSql('CREATE TEMPORARY TABLE __temp__attachments AS SELECT id, type_id, original_filename, show_in_table, name, last_modified, datetime_added, class_name, element_id, path FROM attachments');
$this->addSql('DROP TABLE attachments');
$this->addSql('CREATE TABLE attachments (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, type_id INTEGER NOT NULL, original_filename VARCHAR(255) DEFAULT NULL, show_in_table BOOLEAN NOT NULL, name VARCHAR(255) NOT NULL, last_modified DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, datetime_added DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, class_name VARCHAR(255) NOT NULL, element_id INTEGER NOT NULL, internal_path VARCHAR(255) DEFAULT NULL, external_path VARCHAR(255) DEFAULT NULL, CONSTRAINT FK_47C4FAD6C54C8C93 FOREIGN KEY (type_id) REFERENCES attachment_types (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('INSERT INTO attachments (id, type_id, original_filename, show_in_table, name, last_modified, datetime_added, class_name, element_id, external_path) SELECT id, type_id, original_filename, show_in_table, name, last_modified, datetime_added, class_name, element_id, path FROM __temp__attachments');
$this->addSql('DROP TABLE __temp__attachments');
$this->addSql('CREATE INDEX attachment_element_idx ON attachments (class_name, element_id)');
$this->addSql('CREATE INDEX attachment_name_idx ON attachments (name)');
$this->addSql('CREATE INDEX attachments_idx_class_name_id ON attachments (class_name, id)');
$this->addSql('CREATE INDEX attachments_idx_id_element_id_class_name ON attachments (id, element_id, class_name)');
$this->addSql('CREATE INDEX IDX_47C4FAD6C54C8C93 ON attachments (type_id)');
$this->addSql('CREATE INDEX IDX_47C4FAD61F1F2A24 ON attachments (element_id)');

$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%MEDIA#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%BASE#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%SECURE#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET internal_path=external_path WHERE external_path LIKE \'#%FOOTPRINTS3D#%%\' ESCAPE \'#\'');
$this->addSql('UPDATE attachments SET external_path=NULL WHERE internal_path IS NOT NULL');
}

public function sqLiteDown(Schema $schema): void
{
//Reuse the MySQL down migration:
$this->mySQLDown($schema);
}


}
16 changes: 8 additions & 8 deletions src/Controller/AttachmentFileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ public function download(Attachment $attachment, AttachmentManager $helper): Bin
$this->denyAccessUnlessGranted('show_private', $attachment);
}

if ($attachment->isExternal()) {
throw $this->createNotFoundException('The file for this attachment is external and can not stored locally!');
if (!$attachment->hasInternal()) {
throw $this->createNotFoundException('The file for this attachment is external and not stored locally!');
}

if (!$helper->isFileExisting($attachment)) {
if (!$helper->isInternalFileExisting($attachment)) {
throw $this->createNotFoundException('The file associated with the attachment is not existing!');
}

$file_path = $helper->toAbsoluteFilePath($attachment);
$file_path = $helper->toAbsoluteInternalFilePath($attachment);
$response = new BinaryFileResponse($file_path);

//Set header content disposition, so that the file will be downloaded
Expand All @@ -80,15 +80,15 @@ public function view(Attachment $attachment, AttachmentManager $helper): BinaryF
$this->denyAccessUnlessGranted('show_private', $attachment);
}

if ($attachment->isExternal()) {
throw $this->createNotFoundException('The file for this attachment is external and can not stored locally!');
if (!$attachment->hasInternal()) {
throw $this->createNotFoundException('The file for this attachment is external and not stored locally!');
}

if (!$helper->isFileExisting($attachment)) {
if (!$helper->isInternalFileExisting($attachment)) {
throw $this->createNotFoundException('The file associated with the attachment is not existing!');
}

$file_path = $helper->toAbsoluteFilePath($attachment);
$file_path = $helper->toAbsoluteInternalFilePath($attachment);
$response = new BinaryFileResponse($file_path);

//Set header content disposition, so that the file will be downloaded
Expand Down
2 changes: 1 addition & 1 deletion src/DataFixtures/PartFixtures.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public function load(ObjectManager $manager): void

$attachment = new PartAttachment();
$attachment->setName('Test2');
$attachment->setPath('invalid');
$attachment->setInternalPath('invalid');
$attachment->setShowInTable(true);
$attachment->setAttachmentType($manager->find(AttachmentType::class, 1));
$part->addAttachment($attachment);
Expand Down
72 changes: 42 additions & 30 deletions src/DataTables/AttachmentDataTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public function configure(DataTable $dataTable, array $options): void
{
$dataTable->add('dont_matter', RowClassColumn::class, [
'render' => function ($value, Attachment $context): string {
//Mark attachments with missing files yellow
if(!$this->attachmentHelper->isFileExisting($context)){
//Mark attachments yellow which have an internal file linked that doesn't exist
if($context->hasInternal() && !$this->attachmentHelper->isInternalFileExisting($context)){
return 'table-warning';
}

Expand All @@ -64,8 +64,8 @@ public function configure(DataTable $dataTable, array $options): void
'className' => 'no-colvis',
'render' => function ($value, Attachment $context): string {
if ($context->isPicture()
&& !$context->isExternal()
&& $this->attachmentHelper->isFileExisting($context)) {
&& $this->attachmentHelper->isInternalFileExisting($context)) {

$title = htmlspecialchars($context->getName());
if ($context->getFilename()) {
$title .= ' ('.htmlspecialchars($context->getFilename()).')';
Expand Down Expand Up @@ -93,26 +93,6 @@ public function configure(DataTable $dataTable, array $options): void
$dataTable->add('name', TextColumn::class, [
'label' => 'attachment.edit.name',
'orderField' => 'NATSORT(attachment.name)',
'render' => function ($value, Attachment $context) {
//Link to external source
if ($context->isExternal()) {
return sprintf(
'<a href="%s" class="link-external">%s</a>',
htmlspecialchars((string) $context->getURL()),
htmlspecialchars($value)
);
}

if ($this->attachmentHelper->isFileExisting($context)) {
return sprintf(
'<a href="%s" target="_blank" data-no-ajax>%s</a>',
$this->entityURLGenerator->viewURL($context),
htmlspecialchars($value)
);
}

return $value;
},
]);

$dataTable->add('attachment_type', TextColumn::class, [
Expand All @@ -136,25 +116,57 @@ public function configure(DataTable $dataTable, array $options): void
),
]);

$dataTable->add('filename', TextColumn::class, [
'label' => $this->translator->trans('attachment.table.filename'),
$dataTable->add('internal_link', TextColumn::class, [
'label' => 'attachment.table.internal_file',
'propertyPath' => 'filename',
'render' => function ($value, Attachment $context) {
if ($this->attachmentHelper->isInternalFileExisting($context)) {
return sprintf(
'<a href="%s" target="_blank" data-no-ajax>%s</a>',
$this->entityURLGenerator->viewURL($context),
htmlspecialchars($value)
);
}

return $value;
}
]);

$dataTable->add('external_link', TextColumn::class, [
'label' => 'attachment.table.external_link',
'propertyPath' => 'host',
'render' => function ($value, Attachment $context) {
if ($context->hasExternal()) {
return sprintf(
'<a href="%s" class="link-external">%s</a>',
htmlspecialchars((string) $context->getExternalPath()),
htmlspecialchars($value)
);
}

return $value;
}
]);

$dataTable->add('filesize', TextColumn::class, [
'label' => $this->translator->trans('attachment.table.filesize'),
'render' => function ($value, Attachment $context) {
if ($context->isExternal()) {
if (!$context->hasInternal()) {
return sprintf(
'<span class="badge bg-primary">
<i class="fas fa-globe fa-fw"></i>%s
</span>',
$this->translator->trans('attachment.external')
$this->translator->trans('attachment.external_only')
);
}

if ($this->attachmentHelper->isFileExisting($context)) {
return $this->attachmentHelper->getHumanFileSize($context);
if ($this->attachmentHelper->isInternalFileExisting($context)) {
return sprintf(
'<span class="badge bg-secondary">
<i class="fas fa-hdd fa-fw"></i> %s
</span>',
$this->attachmentHelper->getHumanFileSize($context)
);
}

return sprintf(
Expand Down
Loading
Loading