From a0b185dcda853686cab04e88f9a8e605edcf7d99 Mon Sep 17 00:00:00 2001 From: Audrius Date: Sat, 27 Jun 2026 03:15:45 +0200 Subject: [PATCH] Accept child-theme zips without explicit directory entries processCheckZipFormat() only recognised the required "config" folder when the uploaded archive contained an explicit "config/" directory entry: it collected the root level by keeping entries whose path had a single segment after array_filter(), which a bare directory entry produces but a file entry such as "config/theme.yml" never does. Archives produced by tools that omit directory entries (a very common case when re-zipping the edited child theme) therefore failed validation with "The file is not valid." even though their structure was correct. Inspect the first path segment of every entry instead, so the config folder is detected whether it is described explicitly or only implicitly through the files it contains. --- controllers/admin/AdminPsThemeCustoAdvanced.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/controllers/admin/AdminPsThemeCustoAdvanced.php b/controllers/admin/AdminPsThemeCustoAdvanced.php index 01cf59f..bfcee28 100755 --- a/controllers/admin/AdminPsThemeCustoAdvanced.php +++ b/controllers/admin/AdminPsThemeCustoAdvanced.php @@ -419,9 +419,14 @@ public function processCheckZipFormat($sZipPath) for ($i = 0; $i < $oZip->numFiles; ++$i) { $aZipElement = array_filter(explode('/', $oZip->getNameIndex($i))); - if (count($aZipElement) == 1) { - $aRootFilesAndFolders[] = $aZipElement[0]; + if (empty($aZipElement)) { + continue; } + // Collect the first path segment of every entry. The "config" folder may be present + // only implicitly (e.g. "config/theme.yml") when the archive carries no explicit + // directory entries, so relying on a standalone "config/" entry rejected otherwise + // valid zips with "The file is not valid.". + $aRootFilesAndFolders[] = reset($aZipElement); } $oZip->close();