$paths) { $paths = (array) $paths; foreach ($paths as $path) { $absolutePath = $modulePath.'/'.$path; if (is_dir($absolutePath)) { $loader->addPsr4($namespace, $absolutePath, true); } } } } // files 오토로드 (helpers.php 등) if (! empty($composerData['autoload']['files'])) { foreach ($composerData['autoload']['files'] as $file) { $absoluteFile = $modulePath.'/'.$file; if (file_exists($absoluteFile)) { require_once $absoluteFile; } } } } } } // _bundled 플러그인 오토로드 (prepend) $bundledPluginsDir = __DIR__.'/../plugins/_bundled'; if (is_dir($bundledPluginsDir)) { $bundledPlugins = array_filter(scandir($bundledPluginsDir), function ($dir) use ($bundledPluginsDir) { return $dir !== '.' && $dir !== '..' && is_dir($bundledPluginsDir.'/'.$dir); }); foreach ($bundledPlugins as $pluginDir) { $pluginPath = $bundledPluginsDir.'/'.$pluginDir; // _bundled 식별자 기록 (classmap 중복 방지용) $bundledExtensionIdentifiers[] = $pluginDir; // Classmap 선점 (plugin.php) // class_exists 가드: artisan 초기 부팅에서 활성 디렉토리 버전이 로드되었을 수 있음 $pluginPhp = $pluginPath.'/plugin.php'; if (file_exists($pluginPhp)) { $parts = explode('-', $pluginDir); $vendor = ucfirst($parts[0]); $plgName = isset($parts[1]) ? str_replace('_', '', ucwords($parts[1], '_')) : ''; $pluginClass = "Plugins\\{$vendor}\\{$plgName}\\Plugin"; if (! class_exists($pluginClass, false)) { require_once $pluginPhp; } } // composer.json에서 오토로드 정보 읽기 $composerJson = $pluginPath.'/composer.json'; if (file_exists($composerJson)) { $composerData = json_decode(file_get_contents($composerJson), true); // PSR-4 네임스페이스 prepend 등록 if (! empty($composerData['autoload']['psr-4'])) { foreach ($composerData['autoload']['psr-4'] as $namespace => $paths) { $paths = (array) $paths; foreach ($paths as $path) { $absolutePath = $pluginPath.'/'.$path; if (is_dir($absolutePath)) { $loader->addPsr4($namespace, $absolutePath, true); } } } } // files 오토로드 (helpers.php 등) if (! empty($composerData['autoload']['files'])) { foreach ($composerData['autoload']['files'] as $file) { $absoluteFile = $pluginPath.'/'.$file; if (file_exists($absoluteFile)) { require_once $absoluteFile; } } } } } } // 확장(모듈/플러그인) 오토로드 등록 $extensionAutoloadFile = __DIR__.'/../bootstrap/cache/autoload-extensions.php'; if (file_exists($extensionAutoloadFile)) { $extensionAutoloads = require $extensionAutoloadFile; // PSR-4 네임스페이스 등록 // _bundled에서 이미 prepend로 등록된 확장의 활성 디렉토리 PSR-4 경로는 스킵 // (Windows에서 대소문자 미구분으로 plugin.php = Plugin.php가 되어 중복 로드 발생 방지) if (! empty($extensionAutoloads['psr4'])) { foreach ($extensionAutoloads['psr4'] as $namespace => $paths) { $paths = (array) $paths; foreach ($paths as $path) { // _bundled 식별자와 일치하는 경로는 스킵 $skip = false; foreach ($bundledExtensionIdentifiers as $identifier) { if (str_contains($path, '/'.$identifier.'/')) { $skip = true; break; } } if ($skip) { continue; } $absolutePath = __DIR__.'/../'.$path; if (is_dir($absolutePath)) { $loader->addPsr4($namespace, $absolutePath); } } } } // Classmap 파일 로드 (module.php, plugin.php) // _bundled에서 이미 로드된 확장의 classmap은 스킵 (클래스 중복 선언 방지) if (! empty($extensionAutoloads['classmap'])) { foreach ($extensionAutoloads['classmap'] as $file) { // _bundled 식별자와 일치하는 경로인지 확인 // 예: "modules/sirsoft-board/module.php" → 식별자 "sirsoft-board" $skip = false; foreach ($bundledExtensionIdentifiers as $identifier) { if (str_contains($file, '/'.$identifier.'/')) { $skip = true; break; } } if ($skip) { continue; } $absolutePath = __DIR__.'/../'.$file; if (file_exists($absolutePath)) { require_once $absolutePath; } } } } // 모듈/플러그인 테스트 네임스페이스 등록 (tests/ 디렉토리) $modulesDir = __DIR__.'/../modules'; if (is_dir($modulesDir)) { $modules = array_filter(scandir($modulesDir), function ($dir) use ($modulesDir) { return $dir !== '.' && $dir !== '..' && is_dir($modulesDir.'/'.$dir.'/tests'); }); foreach ($modules as $moduleDir) { // sirsoft-ecommerce -> Modules\Sirsoft\Ecommerce\Tests $parts = explode('-', $moduleDir); $vendor = ucfirst($parts[0]); $moduleName = isset($parts[1]) ? str_replace('_', '', ucwords($parts[1], '_')) : ''; $namespace = "Modules\\{$vendor}\\{$moduleName}\\Tests\\"; $testsPath = $modulesDir.'/'.$moduleDir.'/tests/'; if (is_dir($testsPath)) { $loader->addPsr4($namespace, $testsPath); } } } // _bundled 모듈 테스트 네임스페이스 등록 (prepend) $bundledModulesDir = __DIR__.'/../modules/_bundled'; if (is_dir($bundledModulesDir)) { $bundledModules = array_filter(scandir($bundledModulesDir), function ($dir) use ($bundledModulesDir) { return $dir !== '.' && $dir !== '..' && is_dir($bundledModulesDir.'/'.$dir.'/tests'); }); foreach ($bundledModules as $moduleDir) { $parts = explode('-', $moduleDir); $vendor = ucfirst($parts[0]); $moduleName = isset($parts[1]) ? str_replace('_', '', ucwords($parts[1], '_')) : ''; $namespace = "Modules\\{$vendor}\\{$moduleName}\\Tests\\"; $testsPath = $bundledModulesDir.'/'.$moduleDir.'/tests/'; if (is_dir($testsPath)) { $loader->addPsr4($namespace, $testsPath, true); } } } // 플러그인 소스 및 테스트 네임스페이스 등록 // (미설치 플러그인도 테스트할 수 있도록 autoload-extensions.php 보완) $pluginsDir = __DIR__.'/../plugins'; if (is_dir($pluginsDir)) { $plugins = array_filter(scandir($pluginsDir), function ($dir) use ($pluginsDir) { return $dir !== '.' && $dir !== '..' && is_dir($pluginsDir.'/'.$dir); }); foreach ($plugins as $pluginDir) { // sirsoft-tosspayments -> Plugins\Sirsoft\Tosspayments $parts = explode('-', $pluginDir); $vendor = ucfirst($parts[0]); $pluginName = isset($parts[1]) ? str_replace('_', '', ucwords($parts[1], '_')) : ''; // 소스 네임스페이스 등록 (autoload-extensions.php에 없을 수 있음) $srcPath = $pluginsDir.'/'.$pluginDir.'/src/'; if (is_dir($srcPath)) { $srcNamespace = "Plugins\\{$vendor}\\{$pluginName}\\"; $loader->addPsr4($srcNamespace, $srcPath); } // 테스트 네임스페이스 등록 $testsPath = $pluginsDir.'/'.$pluginDir.'/tests/'; if (is_dir($testsPath)) { $testNamespace = "Plugins\\{$vendor}\\{$pluginName}\\Tests\\"; $loader->addPsr4($testNamespace, $testsPath); } } } // _bundled 플러그인 테스트 네임스페이스 등록 (prepend) $bundledPluginsDir = __DIR__.'/../plugins/_bundled'; if (is_dir($bundledPluginsDir)) { $bundledPlugins = array_filter(scandir($bundledPluginsDir), function ($dir) use ($bundledPluginsDir) { return $dir !== '.' && $dir !== '..' && is_dir($bundledPluginsDir.'/'.$dir.'/tests'); }); foreach ($bundledPlugins as $pluginDir) { $parts = explode('-', $pluginDir); $vendor = ucfirst($parts[0]); $pluginName = isset($parts[1]) ? str_replace('_', '', ucwords($parts[1], '_')) : ''; $testsPath = $bundledPluginsDir.'/'.$pluginDir.'/tests/'; if (is_dir($testsPath)) { $testNamespace = "Plugins\\{$vendor}\\{$pluginName}\\Tests\\"; $loader->addPsr4($testNamespace, $testsPath, true); } } }