@@ -61,9 +61,21 @@ public function initialize(Server $server): void {
6161 $ this ->server ->on ('afterMethod:GET ' , $ this ->afterDownload (...), 999 );
6262 }
6363
64+ /**
65+ * Recursively iterate over all nodes in a folder.
66+ */
67+ protected function iterateNodes (NcNode $ node ): iterable {
68+ yield $ node ;
69+
70+ if ($ node instanceof NcFolder) {
71+ foreach ($ node ->getDirectoryListing () as $ childNode ) {
72+ yield from $ this ->iterateNodes ($ childNode );
73+ }
74+ }
75+ }
76+
6477 /**
6578 * Adding a node to the archive streamer.
66- * This will recursively add new nodes to the stream if the node is a directory.
6779 */
6880 protected function streamNode (Streamer $ streamer , NcNode $ node , string $ rootPath ): void {
6981 // Remove the root path from the filename to make it relative to the requested folder
@@ -79,10 +91,6 @@ protected function streamNode(Streamer $streamer, NcNode $node, string $rootPath
7991 $ streamer ->addFileFromStream ($ resource , $ filename , $ node ->getSize (), $ mtime );
8092 } elseif ($ node instanceof NcFolder) {
8193 $ streamer ->addEmptyDir ($ filename , $ mtime );
82- $ content = $ node ->getDirectoryListing ();
83- foreach ($ content as $ subNode ) {
84- $ this ->streamNode ($ streamer , $ subNode , $ rootPath );
85- }
8694 }
8795 }
8896
@@ -137,7 +145,20 @@ public function handleDownload(Request $request, Response $response): ?bool {
137145 }
138146
139147 $ folder = $ node ->getNode ();
140- $ event = new BeforeZipCreatedEvent ($ folder , $ files );
148+ $ rootNodes = empty ($ files ) ? $ folder ->getDirectoryListing () : [];
149+ foreach ($ files as $ path ) {
150+ $ child = $ node ->getChild ($ path );
151+ assert ($ child instanceof Node);
152+ $ rootNodes [] = $ child ->getNode ();
153+ }
154+ $ allNodes = [];
155+ foreach ($ rootNodes as $ rootNode ) {
156+ foreach ($ this ->iterateNodes ($ rootNode ) as $ node ) {
157+ $ allNodes [] = $ node ;
158+ }
159+ }
160+
161+ $ event = new BeforeZipCreatedEvent ($ folder , $ files , $ allNodes );
141162 $ this ->eventDispatcher ->dispatchTyped ($ event );
142163 if ((!$ event ->isSuccessful ()) || $ event ->getErrorMessage () !== null ) {
143164 $ errorMessage = $ event ->getErrorMessage ();
@@ -149,13 +170,7 @@ public function handleDownload(Request $request, Response $response): ?bool {
149170 // Downloading was denied by an app
150171 throw new Forbidden ($ errorMessage );
151172 }
152-
153- $ content = empty ($ files ) ? $ folder ->getDirectoryListing () : [];
154- foreach ($ files as $ path ) {
155- $ child = $ node ->getChild ($ path );
156- assert ($ child instanceof Node);
157- $ content [] = $ child ->getNode ();
158- }
173+ $ allNodes = $ event ->getNodes ();
159174
160175 $ archiveName = $ folder ->getName ();
161176 if (count (explode ('/ ' , trim ($ folder ->getPath (), '/ ' ), 3 )) === 2 ) {
@@ -169,13 +184,13 @@ public function handleDownload(Request $request, Response $response): ?bool {
169184 $ rootPath = dirname ($ folder ->getPath ());
170185 }
171186
172- $ streamer = new Streamer ($ tarRequest , -1 , count ($ content ), $ this ->timezoneFactory );
187+ $ streamer = new Streamer ($ tarRequest , -1 , count ($ rootNodes ), $ this ->timezoneFactory );
173188 $ streamer ->sendHeaders ($ archiveName );
174189 // For full folder downloads we also add the folder itself to the archive
175190 if (empty ($ files )) {
176191 $ streamer ->addEmptyDir ($ archiveName );
177192 }
178- foreach ($ content as $ node ) {
193+ foreach ($ allNodes as $ node ) {
179194 $ this ->streamNode ($ streamer , $ node , $ rootPath );
180195 }
181196 $ streamer ->finalize ();
0 commit comments