From 40db304331fec25f15c380204d19d43a7f6e0873 Mon Sep 17 00:00:00 2001 From: LebToki <957618+LebToki@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:56:57 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[performance=20improvement]?= =?UTF-8?q?=20Replace=20scandir()=20with=20FilesystemIterator=20in=20listP?= =?UTF-8?q?rojects()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/api/projects.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/public/api/projects.php b/public/api/projects.php index 5f915e4..5452824 100644 --- a/public/api/projects.php +++ b/public/api/projects.php @@ -166,22 +166,31 @@ function listProjects($basePath) { return $projects; } - $dirs = scandir($basePath); - foreach ($dirs as $dir) { - if ($dir === '.' || $dir === '..') continue; + // ⚡ Bolt: Replace scandir() with FilesystemIterator to reduce memory footprint via lazy iteration over large directories + $iterator = new FilesystemIterator($basePath, FilesystemIterator::SKIP_DOTS); + + foreach ($iterator as $fileInfo) { + if (!$fileInfo->isDir()) continue; - $fullPath = $basePath . '/' . $dir; - if (!is_dir($fullPath)) continue; + $dir = $fileInfo->getFilename(); + $fullPath = str_replace('\\', '/', $fileInfo->getPathname()); // Skip hidden directories and common non-project dirs if (strpos($dir, '.') === 0) continue; if (in_array($dir, ['node_modules', 'vendor', '__pycache__', '.git'])) continue; + $modified = date('Y-m-d H:i'); // Fallback + try { + $modified = date('Y-m-d H:i', $fileInfo->getMTime()); + } catch (RuntimeException $e) { + // Ignore unreadable files or broken symlinks to prevent API crash + } + $projects[] = [ 'name' => $dir, 'path' => $fullPath, 'type' => detectProjectType($fullPath), - 'modified' => date('Y-m-d H:i', filemtime($fullPath)), + 'modified' => $modified, ]; }