feat: add client platform type with detection and structure definition

Client repos (WaaS) are managed Joomla sites — not extensions. They have
src/ with site structure PLUS deployment configs (sftp-config, monitoring,
sync scripts). Detection prioritizes client over joomla when deployment
markers are present.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Miller
2026-05-09 17:40:20 -05:00
parent 0e82802f0c
commit 395921282e
2 changed files with 223 additions and 194 deletions
+65 -2
View File
@@ -44,6 +44,7 @@ class AutoDetectPlatform extends CLIApp
private PluginFactory $pluginFactory;
private array $detectionResults = [
'client' => ['score' => 0, 'indicators' => []],
'joomla' => ['score' => 0, 'indicators' => []],
'dolibarr' => ['score' => 0, 'indicators' => []],
'nodejs' => ['score' => 0, 'indicators' => []],
@@ -124,6 +125,9 @@ class AutoDetectPlatform extends CLIApp
$this->log("Plugin system did not detect type, using legacy detection", 'WARNING');
// Run platform detection using legacy methods
// Client must run BEFORE Joomla — client repos contain Joomla dirs
// but are NOT Joomla extensions
$this->detectClient($repoPath);
$this->detectJoomla($repoPath);
$this->detectDolibarr($repoPath);
$this->detectNodeJS($repoPath);
@@ -166,6 +170,65 @@ class AutoDetectPlatform extends CLIApp
return 0;
}
/**
* Detect client site repository.
* Client repos have src/ with Joomla site structure PLUS deployment
* configs (sftp-config/, monitoring/). They are NOT Joomla extensions.
*/
private function detectClient(string $repoPath): void
{
$score = 0;
$indicators = [];
// Strong indicators: deployment/monitoring configs
$clientMarkers = [
'scripts/sftp-config' => 30,
'scripts/sftp-config/sftp-config.dev.json' => 10,
'scripts/sftp-config/sftp-config.rs.json' => 10,
'monitoring/grafana' => 20,
'scripts/sync-dev-to-live.sh' => 15,
'scripts/joomla-monitor.sh' => 10,
'scripts/joomla-monitor.sites.conf' => 10,
];
foreach ($clientMarkers as $path => $weight) {
$full = $repoPath . '/' . $path;
if (is_dir($full) || is_file($full)) {
$score += $weight;
$indicators[] = "Found: {$path} (+{$weight})";
}
}
// Site structure inside src/ (not at root — that would be a Joomla extension)
$siteDirs = ['src/administrator', 'src/components', 'src/plugins', 'src/templates', 'src/media'];
$siteDirCount = 0;
foreach ($siteDirs as $dir) {
if (is_dir($repoPath . '/' . $dir)) {
$siteDirCount++;
}
}
if ($siteDirCount >= 3) {
$score += 20;
$indicators[] = "Joomla site structure in src/ ({$siteDirCount}/5 dirs)";
}
// Negative: if there's a Joomla manifest XML in src/, it's an extension not a client
$manifests = glob($repoPath . '/src/*.xml');
foreach ($manifests ?: [] as $xml) {
$content = @file_get_contents($xml);
if ($content && preg_match('/<extension\s+type="(component|module|plugin|template|package)"/', $content)) {
$score -= 50;
$indicators[] = "Has Joomla extension manifest — likely extension, not client";
break;
}
}
$this->detectionResults['client'] = [
'score' => max(0, $score),
'indicators' => $indicators,
];
}
private function detectJoomla(string $repoPath): void
{
$score = 0;
@@ -639,8 +702,8 @@ class AutoDetectPlatform extends CLIApp
$indicators[] = "Found interactive setup wizard";
}
// Check for .mokostandards platform declaration
$mokoFiles = ["{$repoPath}/.gitea/.mokostandards", "{$repoPath}/.github/.mokostandards"];
// Check for .moko-platform platform declaration
$mokoFiles = ["{$repoPath}/.gitea/.moko-platform", "{$repoPath}/.github/.moko-platform"];
foreach ($mokoFiles as $mokoFile) {
if (file_exists($mokoFile)) {
$content = @file_get_contents($mokoFile);