Make DevtoolsPackageArchive::openArchive() more efficient
authorTim Düsterhus <duesterhus@woltlab.com>
Thu, 11 Feb 2021 11:10:49 +0000 (12:10 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 11 Feb 2021 11:10:49 +0000 (12:10 +0100)
Resolves #3830

wcfsetup/install/files/lib/system/devtools/package/DevtoolsPackageArchive.class.php

index a824a7aafe0cf4fa2982e2dbce94f1294b8f7113..bbb540bce2bbeb95a928a1555246a6a26103006e 100644 (file)
@@ -6,8 +6,6 @@ use wcf\system\package\PackageArchive;
 use wcf\system\package\plugin\ACPTemplatePackageInstallationPlugin;
 use wcf\system\package\plugin\FilePackageInstallationPlugin;
 use wcf\system\package\plugin\TemplatePackageInstallationPlugin;
-use wcf\system\Regex;
-use wcf\util\DirectoryUtil;
 use wcf\util\FileUtil;
 
 /**
@@ -39,13 +37,55 @@ class DevtoolsPackageArchive extends PackageArchive
         $projectDir = FileUtil::addTrailingSlash(
             FileUtil::unifyDirSeparator(\realpath(\dirname($this->packageXmlPath)))
         );
-        $readFiles = DirectoryUtil::getInstance($projectDir)->getFiles(
-            \SORT_ASC,
-            // ignore folders whose contents are delivered as archives by default
-            // and ignore dotfiles and dotdirectories
-            Regex::compile('^' . \preg_quote($projectDir) . '(acptemplates|files|templates|\.)'),
-            true
+
+        $it = new \RecursiveIteratorIterator(
+            new \RecursiveCallbackFilterIterator(
+                new \RecursiveDirectoryIterator($projectDir),
+                static function (\SplFileInfo $current, string $key, \RecursiveDirectoryIterator $it) {
+                    // Skip '.' and '..'.
+                    if ($it->isDot()) {
+                        return false;
+                    }
+
+                    // Skip hidden files.
+                    if ($current->getFilename()[0] === '.') {
+                        return false;
+                    }
+
+                    if ($current->isDir()) {
+                        // Check if we are in the project root.
+                        if ($it->getSubPath() === '') {
+                            // Skip acptemplates / files / templates.
+                            if (
+                                \preg_match(
+                                    '/^(acptemplates|files|templates)(_[a-z0-9]+)?$/',
+                                    $current->getFilename()
+                                )
+                            ) {
+                                return false;
+                            }
+
+                            // Skip node_modules and vendor.
+                            if (\preg_match('/^(node_modules|vendor)$/', $current->getFilename())) {
+                                return false;
+                            }
+
+                            // Skip TypeScript source files.
+                            if (\preg_match('/^ts$/', $current->getFilename())) {
+                                return false;
+                            }
+                        }
+
+                        return true;
+                    }
+
+                    return true;
+                }
+            )
         );
+        $readFiles = \array_map(static function (\SplFileInfo $f) {
+            return $f->getPathname();
+        }, \iterator_to_array($it));
 
         $files = [];
         foreach ($readFiles as $file) {