From a7d0628a130dd2b4aaf7056246e80300ac713105 Mon Sep 17 00:00:00 2001 From: F4ilji Date: Sat, 4 Jul 2026 22:31:10 +0500 Subject: [PATCH] fix(vikon): use module root as FM sync base path instead of files/ subdir Root files (index.html, file_stubs/) and non-3-letter directories now go to module root where VIKON expects them, not into files/ subdirectory. dir_name from FM API is relative to module root. --- .../Actions/SyncFilesAction.php | 180 ++++++++---------- .../Actions/UpdateCoreAction.php | 19 +- 2 files changed, 84 insertions(+), 115 deletions(-) diff --git a/app/Containers/VikonIntegration/Actions/SyncFilesAction.php b/app/Containers/VikonIntegration/Actions/SyncFilesAction.php index f43c9ad..9a5f68d 100644 --- a/app/Containers/VikonIntegration/Actions/SyncFilesAction.php +++ b/app/Containers/VikonIntegration/Actions/SyncFilesAction.php @@ -16,31 +16,35 @@ class SyncFilesAction public function run(int $moduleId, string $accessToken): string { $modulePath = $this->publicPath . '/' . $this->getModuleName($moduleId); - $filesDir = $modulePath . '/files'; Log::info('Vikon FM: starting sync', ['module' => $moduleId]); - $dirs = $this->getUsedDirNames($moduleId, $accessToken); - Log::info('Vikon FM: directories from FM', ['dirs' => $dirs]); + $dirIds = $this->getUsedDirNames($moduleId, $accessToken); + Log::info('Vikon FM: got dir identifiers', ['count' => count($dirIds)]); - foreach ($dirs as $dir) { - if (!File::isDirectory($filesDir . '/' . $dir)) { - File::makeDirectory($filesDir . '/' . $dir, 0755, true, true); - } + $identities = []; + + $rootFiles = $this->getFileIdentitiesFromRoot($moduleId, $accessToken); + $identities = array_merge($identities, $rootFiles); + Log::info('Vikon FM: root file identities', ['count' => count($rootFiles)]); + + foreach ($dirIds as $dirId) { + $dirFiles = $this->getFileIdentitiesFromSubDir($dirId, $moduleId, $accessToken); + $identities = array_merge($identities, $dirFiles); } + Log::info('Vikon FM: total file identities', ['count' => count($identities)]); $synced = 0; - - $synced += $this->syncRootDir($moduleId, $accessToken, $filesDir); - - foreach ($dirs as $dir) { - $synced += $this->syncSubDir($dir, $moduleId, $accessToken, $filesDir); + foreach ($identities as $identity) { + $result = $this->downloadByIdentity($identity, $moduleId, $modulePath, $accessToken); + if ($result) $synced++; } - $synced += $this->syncNewFiles($moduleId, $accessToken, $filesDir); + $newSynced = $this->syncNewFiles($moduleId, $accessToken, $modulePath); - Log::info('Vikon FM: sync done', ['module' => $moduleId, 'synced' => $synced]); - return "Синхронизировано: {$synced} файлов"; + $total = $synced + $newSynced; + Log::info('Vikon FM: sync complete', ['downloaded' => $synced, 'new' => $newSynced]); + return "Синхронизировано: {$total} файлов"; } private function getModuleName(int $moduleId): string @@ -60,77 +64,76 @@ class SyncFilesAction $accessToken, 'filemanager' ); - $body = $response->json(); return $body['directories'] ?? []; } - private function syncRootDir(int $moduleId, string $accessToken, string $filesDir): int + private function getFileIdentitiesFromRoot(int $moduleId, string $accessToken): array { $response = $this->http->getWithToken( "sync/getFileNamesFromRootDirectoryByModule?moduleId={$moduleId}", $accessToken, 'filemanager' ); - $body = $response->json(); $files = $body['files'] ?? []; - if (empty($files)) { - return 0; - } - - $synced = 0; - foreach ($files as $file) { - $name = $file['n'] ?? null; - $identity = $file['i'] ?? null; - - if (!$name || !$identity) continue; - - $filePath = $filesDir . '/' . $name; - $this->downloadAndSave($identity, $moduleId, $filePath, $accessToken); - $synced++; - } - - return $synced; + return array_map(fn($f) => $f['i'], array_filter($files, fn($f) => !empty($f['i']))); } - private function syncSubDir(string $dir, int $moduleId, string $accessToken, string $filesDir): int + private function getFileIdentitiesFromSubDir(string $dirId, int $moduleId, string $accessToken): array { $response = $this->http->getWithToken( - "sync/getFileNamesFromSubDirectoryByModule?dir={$dir}&moduleId={$moduleId}", + "sync/getFileNamesFromSubDirectoryByModule?dir={$dirId}&moduleId={$moduleId}", $accessToken, 'filemanager' ); - $body = $response->json(); $files = $body['files'] ?? []; - if (empty($files)) { - return 0; - } - - $dirPath = $filesDir . '/' . $dir; - if (!File::isDirectory($dirPath)) { - File::makeDirectory($dirPath, 0755, true, true); - } - - $synced = 0; - foreach ($files as $file) { - $name = $file['n'] ?? null; - $identity = $file['i'] ?? null; - - if (!$name || !$identity) continue; - - $filePath = $dirPath . '/' . $name; - $this->downloadAndSave($identity, $moduleId, $filePath, $accessToken); - $synced++; - } - - return $synced; + return array_map(fn($f) => $f['i'], array_filter($files, fn($f) => !empty($f['i']))); } - private function syncNewFiles(int $moduleId, string $accessToken, string $filesDir): int + private function downloadByIdentity(string $identity, int $moduleId, string $modulePath, string $accessToken): bool + { + try { + $infoResp = $this->http->getWithToken( + "sync/getFileByIdentityInfo?identity={$identity}", + $accessToken, + 'filemanager' + ); + $info = $infoResp->json(); + + if (empty($info['identity']) || empty($info['file_name'])) { + return false; + } + + $dirName = $info['dir_name'] ?? null; + $targetDir = $modulePath; + if ($dirName) { + $targetDir = $modulePath . '/' . $dirName; + } + + $content = $this->http->downloadWithToken( + "sync/downloadFileBinaryForSync?identity={$info['identity']}&moduleId={$moduleId}", + $accessToken, + 'filemanager' + ); + + if (!File::isDirectory($targetDir)) { + File::makeDirectory($targetDir, 0755, true, true); + } + + $targetPath = $targetDir . '/' . $info['file_name']; + file_put_contents($targetPath, $content); + return true; + } catch (\Throwable $e) { + Log::warning('Vikon FM: download failed', ['identity' => $identity, 'error' => $e->getMessage()]); + return false; + } + } + + private function syncNewFiles(int $moduleId, string $accessToken, string $modulePath): int { $synced = 0; @@ -140,7 +143,6 @@ class SyncFilesAction $accessToken, 'filemanager' ); - $body = $response->json(); if (empty($body['file_name']) && empty($body['identity'])) { @@ -151,15 +153,19 @@ class SyncFilesAction $filename = $body['file_name']; $directory = $body['dir_name'] ?? null; - $targetDir = $filesDir; - if ($directory) { - $targetDir = $filesDir . '/' . $directory; - if (!File::isDirectory($targetDir)) { - File::makeDirectory($targetDir, 0775, true, true); - } + $targetDir = $directory ? $modulePath . '/' . $directory : $modulePath; + + $content = $this->http->downloadWithToken( + "sync/downloadFileBinary?identity={$identity}", + $accessToken, + 'filemanager' + ); + + if (!File::isDirectory($targetDir)) { + File::makeDirectory($targetDir, 0755, true, true); } - $this->downloadAndSave($identity, $moduleId, $targetDir . '/' . $filename, $accessToken); + file_put_contents($targetDir . '/' . $filename, $content); $this->http->getWithToken( "sync/markNewFileAsLoaded?identity={$identity}&moduleId={$moduleId}", @@ -172,40 +178,4 @@ class SyncFilesAction return $synced; } - - private function downloadAndSave(string $identity, int $moduleId, string $targetPath, string $accessToken): void - { - try { - $infoResponse = $this->http->getWithToken( - "sync/getFileByIdentityInfo?identity={$identity}", - $accessToken, - 'filemanager' - ); - $info = $infoResponse->json(); - - if (empty($info['identity'])) { - Log::warning('Vikon FM: no identity in info response', ['identity' => $identity]); - return; - } - - $content = $this->http->downloadWithToken( - "sync/downloadFileBinaryForSync?identity={$info['identity']}&moduleId={$moduleId}", - $accessToken, - 'filemanager' - ); - - $dir = dirname($targetPath); - if (!File::isDirectory($dir)) { - File::makeDirectory($dir, 0755, true, true); - } - - file_put_contents($targetPath, $content); - } catch (\Throwable $e) { - Log::warning('Vikon FM: failed to download file', [ - 'identity' => $identity, - 'target' => $targetPath, - 'error' => $e->getMessage(), - ]); - } - } } diff --git a/app/Containers/VikonIntegration/Actions/UpdateCoreAction.php b/app/Containers/VikonIntegration/Actions/UpdateCoreAction.php index 1334721..4801312 100644 --- a/app/Containers/VikonIntegration/Actions/UpdateCoreAction.php +++ b/app/Containers/VikonIntegration/Actions/UpdateCoreAction.php @@ -72,26 +72,25 @@ class UpdateCoreAction private function syncFromFM(int $moduleId, string $modulePath, string $accessToken): void { - $filesDir = $modulePath . '/files'; - File::makeDirectory($filesDir, 0755, true, true); + File::makeDirectory($modulePath, 0755, true, true); $dirIds = $this->getUsedDirNames($moduleId, $accessToken); Log::info('Vikon FM: dir identifiers', ['count' => count($dirIds)]); $synced = 0; - $synced += $this->syncDirFiles('root', $moduleId, $filesDir, $accessToken); + $synced += $this->syncDirFiles('root', $moduleId, $modulePath, $accessToken); foreach ($dirIds as $dirId) { - $synced += $this->syncDirFiles($dirId, $moduleId, $filesDir, $accessToken); + $synced += $this->syncDirFiles($dirId, $moduleId, $modulePath, $accessToken); } - $newSynced = $this->syncNewFiles($moduleId, $accessToken, $filesDir); + $newSynced = $this->syncNewFiles($moduleId, $accessToken, $modulePath); Log::info('Vikon FM: sync done', ['synced' => $synced, 'new' => $newSynced]); } - private function syncDirFiles(string $dirId, int $moduleId, string $filesDir, string $accessToken): int + private function syncDirFiles(string $dirId, int $moduleId, string $modulePath, string $accessToken): int { if ($dirId === 'root') { $response = $this->http->getWithToken( @@ -99,14 +98,14 @@ class UpdateCoreAction $accessToken, 'filemanager' ); - $targetDir = $filesDir; + $targetDir = $modulePath; } else { $response = $this->http->getWithToken( "sync/getFileNamesFromSubDirectoryByModule?dir={$dirId}&moduleId={$moduleId}", $accessToken, 'filemanager' ); - $targetDir = $filesDir . '/' . $dirId; + $targetDir = $modulePath . '/' . $dirId; } $files = $response->json()['files'] ?? []; @@ -136,7 +135,7 @@ class UpdateCoreAction return $synced; } - private function syncNewFiles(int $moduleId, string $accessToken, string $filesDir): int + private function syncNewFiles(int $moduleId, string $accessToken, string $modulePath): int { $synced = 0; while (true) { @@ -153,7 +152,7 @@ class UpdateCoreAction $filename = $body['file_name']; $directory = $body['dir_name'] ?? null; - $targetDir = $directory ? $filesDir . '/' . $directory : $filesDir; + $targetDir = $directory ? $modulePath . '/' . $directory : $modulePath; try { $content = $this->http->downloadWithToken(