diff --git a/cli/release_package.php b/cli/release_package.php index c5f83f4..665aaaf 100644 --- a/cli/release_package.php +++ b/cli/release_package.php @@ -270,12 +270,90 @@ class ReleasePackageCli extends CliFramework } } + // Check if sub-source is itself a Joomla package (nested package) + $nestedPkgManifests = glob("{$subSourceDir}/pkg_*.xml") ?: []; + $isNestedPackage = !empty($nestedPkgManifests) && is_dir("{$subSourceDir}/packages"); + $subZip = new \ZipArchive(); if ($subZip->open($subZipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) { $this->log('ERROR', "Failed to create sub-package ZIP: {$subZipPath}"); continue; } - $this->addDirToZip($subZip, $subSourceDir, '', $this->excludePatterns); + + if ($isNestedPackage) { + // Build nested package: zip each sub-extension, then assemble + echo " Building nested package: {$subName}\n"; + $nestedPkgDirs = glob("{$subSourceDir}/packages/*", GLOB_ONLYDIR) ?: []; + + $nestedManifested = []; + foreach ($nestedPkgManifests as $npmf) { + $npmXml = @simplexml_load_file($npmf); + if ($npmXml && isset($npmXml->files)) { + foreach ($npmXml->files->file as $fn) { + $nzn = pathinfo((string) $fn, PATHINFO_FILENAME); + if (!empty($nzn)) { + $nestedManifested[$nzn] = true; + } + } + } + } + + // Use a subdirectory to avoid filename collisions with outer ZIPs + $nestedOutputDir = "{$outputDir}/nested_{$subName}"; + @mkdir($nestedOutputDir, 0755, true); + + foreach ($nestedPkgDirs as $npd) { + $nestedSubName = basename($npd); + if (!empty($nestedManifested) && !isset($nestedManifested[$nestedSubName])) { + continue; + } + $nestedSubZipPath = "{$nestedOutputDir}/{$nestedSubName}.zip"; + $nsZip = new \ZipArchive(); + if ($nsZip->open($nestedSubZipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) !== true) { + continue; + } + $this->addDirToZip($nsZip, $npd, '', $this->excludePatterns); + $nsZip->close(); + $subZip->addFile($nestedSubZipPath, "packages/{$nestedSubName}.zip"); + echo " Nested sub: {$nestedSubName}.zip\n"; + } + + // Patch nested manifest: ensure folder="packages" so Joomla finds sub-ZIPs + foreach ($nestedPkgManifests as $npmf) { + $npmContent = file_get_contents($npmf); + if ($npmContent !== false + && strpos($npmContent, '') !== false + && strpos($npmContent, 'folder="packages"') === false + ) { + $npmContent = str_replace('', '', $npmContent); + file_put_contents($npmf, $npmContent); + echo " Fixed: added folder=\"packages\" to " . basename($npmf) . "\n"; + } + } + + // Add top-level files (manifest, script, etc.) with exclude filter + $nestedTopFiles = array_merge( + glob("{$subSourceDir}/*.xml") ?: [], + glob("{$subSourceDir}/*.php") ?: [] + ); + foreach ($nestedTopFiles as $ntf) { + if (!$this->isExcluded(basename($ntf), $this->excludePatterns)) { + $subZip->addFile($ntf, basename($ntf)); + } + } + + // Add all top-level directories except packages/ + $nestedTopDirs = glob("{$subSourceDir}/*", GLOB_ONLYDIR) ?: []; + foreach ($nestedTopDirs as $ntd) { + $ndName = basename($ntd); + if ($ndName === 'packages') { + continue; + } + $this->addDirToZip($subZip, $ntd, $ndName, $this->excludePatterns); + } + } else { + $this->addDirToZip($subZip, $subSourceDir, '', $this->excludePatterns); + } $subZip->close(); $zip->addFile($subZipPath, "packages/{$subName}.zip");