getModuleConfig($moduleId); $modulePath = $this->basePath . '/' . $moduleConfig['path']; $filesPath = $modulePath . '/files'; // Step 1: Get directories list from Vikon file manager $response = $this->callVikonApiTask->getWithToken( 'sync/getUsedDirNamesByModule?moduleId=' . $moduleId, $accessToken, 'filemanager' ); $body = $response->json(); if (!isset($body['directories']) || !is_array($body['directories'])) { throw new \RuntimeException('Невалидный ответ от файлового сервера'); } $directories = $body['directories']; // Step 2: Remove unknown directories $this->cleanUnknownDirectories($filesPath, $directories, $modulePath); // Step 3: Get files that need to be synced $filesToSync = $this->getFilesToSync($filesPath, $moduleId, $accessToken); return [ 'directories' => $directories, 'files_to_sync' => $filesToSync, ]; } /** * Get module configuration * * @throws \RuntimeException */ private function getModuleConfig(int $moduleId): array { if (!isset($this->modulesConfig[$moduleId])) { throw new \RuntimeException('Неизвестный идентификатор модуля'); } return $this->modulesConfig[$moduleId]; } /** * Remove directories that are not in the known list */ private function cleanUnknownDirectories(string $filesPath, array $knownDirs, string $modulePath): void { // Guard against empty/malformed remote list if (empty($knownDirs)) { Log::warning('Vikon sync: empty directory list from remote, skipping cleanup'); return; } if (!File::isDirectory($filesPath)) { return; } $existingDirs = File::directories($filesPath); foreach ($existingDirs as $dir) { $dirName = basename($dir); // Check for symlinks before deleting (like old code) if (is_link($dir)) { Log::warning('Vikon sync: skipping symlink during cleanup', [ 'path' => $dir, ]); continue; } if (!in_array($dirName, $knownDirs)) { Log::info('Vikon sync: removing unknown directory', [ 'directory' => $dirName, ]); File::deleteDirectory($dir); } } } /** * Get list of files that need to be synced */ private function getFilesToSync(string $filesPath, int $moduleId, string $accessToken): array { // Get file list from Vikon file manager $response = $this->callVikonApiTask->getWithToken( 'sync/getFileNamesFromRootDirectoryByModule?moduleId=' . $moduleId, $accessToken, 'filemanager' ); $body = $response->json(); if (!isset($body['files']) || !is_array($body['files'])) { return []; } // Build remote files map: name => identity (like old code used $row->i) $remoteFiles = []; foreach ($body['files'] as $file) { if (isset($file['n'])) { $remoteFiles[$file['n']] = $file['i'] ?? null; // n = name, i = identity } } // Compare with local files $localFiles = []; if (File::isDirectory($filesPath)) { $localFilesList = File::files($filesPath); foreach ($localFilesList as $localFile) { $fileName = basename($localFile); $fileSize = filesize($localFile); // Skip empty files (like old code: if (!filesize($fsItemPath))) if ($fileSize > 0) { $localFiles[$fileName] = $fileSize; } } } // Find files that don't exist locally or have different identity $filesToSync = []; foreach ($remoteFiles as $fileName => $fileId) { if (!isset($localFiles[$fileName])) { // File doesn't exist locally $filesToSync[] = [ 'name' => $fileName, 'id' => $fileId, 'reason' => 'missing', ]; } // Note: old code also checked identity mismatch, but identity is only // available from filemanager API. If file exists locally with same name, // we assume it's the correct version (identity match). } return $filesToSync; } }