refactor: front end
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -7,20 +7,17 @@ declare(strict_types=1);
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace KTXM\FileManager\Controllers;
|
||||
namespace KTXM\DocumentsManager\Controllers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use KTXC\Http\Response\JsonResponse;
|
||||
use KTXC\Http\Response\Response;
|
||||
use KTXC\Http\Response\StreamedResponse;
|
||||
use KTXC\SessionIdentity;
|
||||
use KTXC\SessionTenant;
|
||||
use KTXF\Controller\ControllerAbstract;
|
||||
use KTXF\Files\Node\INodeCollectionBase;
|
||||
use KTXF\Files\Node\INodeEntityBase;
|
||||
use KTXF\Routing\Attributes\AuthenticatedRoute;
|
||||
use KTXM\FileManager\Manager;
|
||||
use KTXM\FileManager\Transfer\StreamingZip;
|
||||
use KTXM\DocumentsManager\Manager;
|
||||
use KTXM\DocumentsManager\Transfer\StreamingZip;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
|
||||
@@ -39,7 +36,7 @@ class TransferController extends ControllerAbstract
|
||||
public function __construct(
|
||||
private readonly SessionTenant $tenantIdentity,
|
||||
private readonly SessionIdentity $userIdentity,
|
||||
private Manager $fileManager,
|
||||
private readonly Manager $manager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {}
|
||||
|
||||
@@ -50,21 +47,16 @@ class TransferController extends ControllerAbstract
|
||||
*/
|
||||
#[AuthenticatedRoute(
|
||||
'/download/entity/{provider}/{service}/{collection}/{identifier}',
|
||||
name: 'filemanager.download.entity',
|
||||
name: 'document_manager.download.entity',
|
||||
methods: ['GET']
|
||||
)]
|
||||
public function downloadEntity(
|
||||
string $provider,
|
||||
string $service,
|
||||
string $collection,
|
||||
string $identifier
|
||||
): Response {
|
||||
public function downloadEntity(string $provider, string $service, string $collection, string $identifier): Response {
|
||||
$tenantId = $this->tenantIdentity->identifier();
|
||||
$userId = $this->userIdentity->identifier();
|
||||
|
||||
try {
|
||||
// Fetch entity metadata
|
||||
$entities = $this->fileManager->entityFetch(
|
||||
$entities = $this->manager->entityFetch(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -80,11 +72,10 @@ class TransferController extends ControllerAbstract
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/** @var INodeEntityBase $entity */
|
||||
$entity = $entities[$identifier];
|
||||
|
||||
// Get the stream
|
||||
$stream = $this->fileManager->entityReadStream(
|
||||
$stream = $this->manager->entityReadStream(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -100,22 +91,29 @@ class TransferController extends ControllerAbstract
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$filename = $entity->getLabel() ?? 'download';
|
||||
$mime = $entity->getMime() ?? 'application/octet-stream';
|
||||
$size = $entity->size();
|
||||
$filename = $entity->getProperties()->getLabel() ?? 'download';
|
||||
$mime = $entity->getProperties()->getMime() ?? 'application/octet-stream';
|
||||
$size = $entity->getProperties()->size();
|
||||
|
||||
// Create streamed response
|
||||
$response = new StreamedResponse(function () use ($stream) {
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 65536);
|
||||
@ob_flush();
|
||||
flush();
|
||||
try {
|
||||
while (!feof($stream)) {
|
||||
echo fread($stream, 65536);
|
||||
@ob_flush();
|
||||
flush();
|
||||
}
|
||||
} finally {
|
||||
fclose($stream);
|
||||
}
|
||||
fclose($stream);
|
||||
});
|
||||
|
||||
$response->headers->set('Content-Type', $mime);
|
||||
$response->headers->set('Content-Length', (string) $size);
|
||||
// Only advertise Content-Length when metadata is non-zero; a zero value
|
||||
// would cause clients to believe the file is empty and discard the body.
|
||||
if ($size > 0) {
|
||||
$response->headers->set('Content-Length', (string) $size);
|
||||
}
|
||||
$response->headers->set('Content-Disposition',
|
||||
$response->headers->makeDisposition('attachment', $filename, $this->asciiFallback($filename))
|
||||
);
|
||||
@@ -139,16 +137,10 @@ class TransferController extends ControllerAbstract
|
||||
*/
|
||||
#[AuthenticatedRoute(
|
||||
'/download/archive',
|
||||
name: 'filemanager.download.archive',
|
||||
name: 'manager.download.archive',
|
||||
methods: ['GET']
|
||||
)]
|
||||
public function downloadArchive(
|
||||
string $provider,
|
||||
string $service,
|
||||
array $ids = [],
|
||||
string $collection = null,
|
||||
string $name = 'download'
|
||||
): Response {
|
||||
public function downloadArchive(string $provider, string $service, array $ids = [], ?string $collection = null, string $name = 'download'): Response {
|
||||
$tenantId = $this->tenantIdentity->identifier();
|
||||
$userId = $this->userIdentity->identifier();
|
||||
|
||||
@@ -184,7 +176,7 @@ class TransferController extends ControllerAbstract
|
||||
$zip = new StreamingZip(null, false); // No compression for speed
|
||||
|
||||
foreach ($files as $file) {
|
||||
$stream = $this->fileManager->entityReadStream(
|
||||
$stream = $this->manager->entityReadStream(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -194,12 +186,15 @@ class TransferController extends ControllerAbstract
|
||||
);
|
||||
|
||||
if ($stream !== null) {
|
||||
$zip->addFileFromStream(
|
||||
$file['path'],
|
||||
$stream,
|
||||
$file['modTime'] ?? null
|
||||
);
|
||||
fclose($stream);
|
||||
try {
|
||||
$zip->addFileFromStream(
|
||||
$file['path'],
|
||||
$stream,
|
||||
$file['modTime'] ?? null
|
||||
);
|
||||
} finally {
|
||||
fclose($stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,20 +226,17 @@ class TransferController extends ControllerAbstract
|
||||
*/
|
||||
#[AuthenticatedRoute(
|
||||
'/download/collection/{provider}/{service}/{identifier}',
|
||||
name: 'filemanager.download.collection',
|
||||
name: 'manager.download.collection',
|
||||
methods: ['GET']
|
||||
)]
|
||||
public function downloadCollection(
|
||||
string $provider,
|
||||
string $service,
|
||||
string $identifier
|
||||
): Response {
|
||||
public function downloadCollection(string $provider, string $service, string $identifier): Response {
|
||||
$tenantId = $this->tenantIdentity->identifier();
|
||||
$userId = $this->userIdentity->identifier();
|
||||
|
||||
try {
|
||||
// Fetch collection metadata
|
||||
$collection = $this->fileManager->collectionFetch(
|
||||
/** @var CollectionBaseInterface|null $collection */
|
||||
$collection = $this->manager->collectionFetch(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -280,7 +272,7 @@ class TransferController extends ControllerAbstract
|
||||
if ($file['type'] === 'directory') {
|
||||
$zip->addDirectory($file['path'], $file['modTime'] ?? null);
|
||||
} else {
|
||||
$stream = $this->fileManager->entityReadStream(
|
||||
$stream = $this->manager->entityReadStream(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -290,12 +282,15 @@ class TransferController extends ControllerAbstract
|
||||
);
|
||||
|
||||
if ($stream !== null) {
|
||||
$zip->addFileFromStream(
|
||||
$file['path'],
|
||||
$stream,
|
||||
$file['modTime'] ?? null
|
||||
);
|
||||
fclose($stream);
|
||||
try {
|
||||
$zip->addFileFromStream(
|
||||
$file['path'],
|
||||
$stream,
|
||||
$file['modTime'] ?? null
|
||||
);
|
||||
} finally {
|
||||
fclose($stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,20 +318,14 @@ class TransferController extends ControllerAbstract
|
||||
/**
|
||||
* Resolve a list of entity/collection IDs into a flat file list for archiving
|
||||
*/
|
||||
private function resolveFilesForArchive(
|
||||
string $tenantId,
|
||||
string $userId,
|
||||
string $provider,
|
||||
string $service,
|
||||
?string $collection,
|
||||
array $ids
|
||||
): array {
|
||||
private function resolveFilesForArchive(string $tenantId, string $userId, string $provider, string $service, ?string $collection, array $ids): array {
|
||||
$files = [];
|
||||
|
||||
foreach ($ids as $id) {
|
||||
// Try as entity first
|
||||
if ($collection !== null) {
|
||||
$entities = $this->fileManager->entityFetch(
|
||||
/** @var EntityBaseInterface[] $entities */
|
||||
$entities = $this->manager->entityFetch(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -346,7 +335,6 @@ class TransferController extends ControllerAbstract
|
||||
);
|
||||
|
||||
if (!empty($entities) && isset($entities[$id])) {
|
||||
/** @var INodeEntityBase $entity */
|
||||
$entity = $entities[$id];
|
||||
$files[] = [
|
||||
'type' => 'file',
|
||||
@@ -360,7 +348,8 @@ class TransferController extends ControllerAbstract
|
||||
}
|
||||
|
||||
// Try as collection (folder)
|
||||
$collectionNode = $this->fileManager->collectionFetch(
|
||||
/** @var CollectionBaseInterface|null $collectionNode */
|
||||
$collectionNode = $this->manager->collectionFetch(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -394,10 +383,21 @@ class TransferController extends ControllerAbstract
|
||||
string $provider,
|
||||
string $service,
|
||||
string $collectionId,
|
||||
string $basePath
|
||||
string $basePath,
|
||||
int $depth = 0,
|
||||
int $maxDepth = 20
|
||||
): array {
|
||||
$files = [];
|
||||
|
||||
// Guard against runaway recursion on pathologically deep trees
|
||||
if ($depth > $maxDepth) {
|
||||
$this->logger->warning('Max recursion depth reached, skipping deeper contents', [
|
||||
'collection' => $collectionId,
|
||||
'depth' => $depth,
|
||||
]);
|
||||
return $files;
|
||||
}
|
||||
|
||||
// Add directory entry if we have a path
|
||||
if ($basePath !== '') {
|
||||
$files[] = [
|
||||
@@ -410,7 +410,7 @@ class TransferController extends ControllerAbstract
|
||||
// Get all nodes in this collection using nodeList with recursive=false
|
||||
// We handle recursion ourselves to build proper paths
|
||||
try {
|
||||
$nodes = $this->fileManager->nodeList(
|
||||
$nodes = $this->manager->nodeList(
|
||||
$tenantId,
|
||||
$userId,
|
||||
$provider,
|
||||
@@ -438,7 +438,9 @@ class TransferController extends ControllerAbstract
|
||||
$provider,
|
||||
$service,
|
||||
(string) $node->id(),
|
||||
$nodePath
|
||||
$nodePath,
|
||||
$depth + 1,
|
||||
$maxDepth
|
||||
);
|
||||
$files = array_merge($files, $subFiles);
|
||||
} else {
|
||||
|
||||
1174
lib/Manager.php
1174
lib/Manager.php
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace KTXM\FileManager;
|
||||
namespace KTXM\DocumentsManager;
|
||||
|
||||
use KTXF\Module\ModuleBrowserInterface;
|
||||
use KTXF\Module\ModuleInstanceAbstract;
|
||||
@@ -16,12 +16,12 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||
|
||||
public function handle(): string
|
||||
{
|
||||
return 'file_manager';
|
||||
return 'documents_manager';
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'File Manager';
|
||||
return 'Documents Manager';
|
||||
}
|
||||
|
||||
public function author(): string
|
||||
@@ -31,7 +31,7 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||
|
||||
public function description(): string
|
||||
{
|
||||
return 'File management module for Ktrix - provides file and folder management functionalities';
|
||||
return 'Documents management module for Ktrix - provides document and folder management functionalities';
|
||||
}
|
||||
|
||||
public function version(): string
|
||||
@@ -42,10 +42,10 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||
public function permissions(): array
|
||||
{
|
||||
return [
|
||||
'file_manager' => [
|
||||
'label' => 'Access File Manager',
|
||||
'description' => 'View and access the file manager module',
|
||||
'group' => 'File Management'
|
||||
'documents_manager' => [
|
||||
'label' => 'Access Documents Manager',
|
||||
'description' => 'View and access the documents manager module',
|
||||
'group' => 'Document Management'
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||
public function registerBI(): array {
|
||||
return [
|
||||
'handle' => $this->handle(),
|
||||
'namespace' => 'FileManager',
|
||||
'namespace' => 'DocumentsManager',
|
||||
'version' => $this->version(),
|
||||
'label' => $this->label(),
|
||||
'author' => $this->author(),
|
||||
|
||||
@@ -7,7 +7,7 @@ declare(strict_types=1);
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace KTXM\FileManager\Transfer;
|
||||
namespace KTXM\DocumentsManager\Transfer;
|
||||
|
||||
/**
|
||||
* Native PHP streaming ZIP archive generator
|
||||
|
||||
Reference in New Issue
Block a user