Completed
Push — master ( 048037...5acb93 )
by
unknown
29:31
created
apps/dav/lib/Connector/Sabre/Server.php 2 patches
Indentation   +261 added lines, -261 removed lines patch added patch discarded remove patch
@@ -23,268 +23,268 @@
 block discarded – undo
23 23
  * @see \Sabre\DAV\Server
24 24
  */
25 25
 class Server extends \Sabre\DAV\Server {
26
-	/** @var CachingTree $tree */
27
-
28
-	/**
29
-	 * Tracks queries done by plugins.
30
-	 * @var array<string, array<int, array<string, array{nodes:int,
31
-	 *     queries:int}>>> The keys represent: event name, depth and plugin name
32
-	 */
33
-	private array $pluginQueries = [];
34
-
35
-	public bool $debugEnabled = false;
36
-
37
-	/**
38
-	 * @var array<string, array<int, callable>>
39
-	 */
40
-	private array $originalListeners = [];
41
-
42
-	/**
43
-	 * @var array<string, array<int, callable>>
44
-	 */
45
-	private array $wrappedListeners = [];
46
-
47
-	/**
48
-	 * @see \Sabre\DAV\Server
49
-	 */
50
-	public function __construct($treeOrNode = null) {
51
-		parent::__construct($treeOrNode);
52
-		self::$exposeVersion = false;
53
-		$this->enablePropfindDepthInfinity = true;
54
-	}
55
-
56
-	#[Override]
57
-	public function once(
58
-		string $eventName,
59
-		callable $callBack,
60
-		int $priority = 100,
61
-	): void {
62
-		$this->debugEnabled ? $this->monitorPropfindQueries(
63
-			parent::once(...),
64
-			...\func_get_args(),
65
-		) : parent::once(...\func_get_args());
66
-	}
67
-
68
-	#[Override]
69
-	public function on(
70
-		string $eventName,
71
-		callable $callBack,
72
-		int $priority = 100,
73
-	): void {
74
-		$this->debugEnabled ? $this->monitorPropfindQueries(
75
-			parent::on(...),
76
-			...\func_get_args(),
77
-		) : parent::on(...\func_get_args());
78
-	}
79
-
80
-	/**
81
-	 * Wraps the handler $callBack into a query-monitoring function and calls
82
-	 * $parentFn to register it.
83
-	 */
84
-	private function monitorPropfindQueries(
85
-		callable $parentFn,
86
-		string $eventName,
87
-		callable $callBack,
88
-		int $priority = 100,
89
-	): void {
90
-		$pluginName = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['class'] ?? 'unknown';
91
-		// The NotifyPlugin needs to be excluded as it emits the
92
-		// `preloadCollection` event, which causes many plugins run queries.
93
-		/** @psalm-suppress TypeDoesNotContainType */
94
-		if ($pluginName === PropFindPreloadNotifyPlugin::class || ($eventName !== 'propFind'
95
-				&& $eventName !== 'preloadCollection')) {
96
-			$parentFn($eventName, $callBack, $priority);
97
-			return;
98
-		}
99
-
100
-		$wrappedCallback
101
-			= $this->getMonitoredCallback($callBack, $pluginName, $eventName);
102
-		$this->originalListeners[$eventName][] = $callBack;
103
-		$this->wrappedListeners[$eventName][] = $wrappedCallback;
104
-
105
-		$parentFn($eventName, $wrappedCallback, $priority);
106
-	}
107
-
108
-	public function removeListener(
109
-		string $eventName,
110
-		callable $listener,
111
-	): bool {
112
-		$listenerIndex = null;
113
-		if (isset($this->wrappedListeners[$eventName], $this->originalListeners[$eventName])) {
114
-			$key = array_search(
115
-				$listener,
116
-				$this->originalListeners[$eventName],
117
-				true
118
-			);
119
-			if ($key !== false) {
120
-				$listenerIndex = $key;
121
-				$listener = $this->wrappedListeners[$eventName][$listenerIndex];
122
-			}
123
-		}
124
-		$removed = parent::removeListener($eventName, $listener);
125
-
126
-		if ($removed && $listenerIndex !== null) {
127
-			unset($this->originalListeners[$eventName][$listenerIndex], $this->wrappedListeners[$eventName][$listenerIndex]);
128
-		}
129
-
130
-		return $removed;
131
-	}
132
-
133
-	public function removeAllListeners(?string $eventName = null): void {
134
-		parent::removeAllListeners($eventName);
135
-
136
-		if ($eventName === null) {
137
-			$this->originalListeners = [];
138
-			$this->wrappedListeners = [];
139
-		} else {
140
-			unset($this->wrappedListeners[$eventName], $this->originalListeners[$eventName]);
141
-		}
142
-	}
143
-
144
-	/**
145
-	 * Returns a callable that wraps $callBack with code that monitors and
146
-	 * records queries per plugin.
147
-	 */
148
-	private function getMonitoredCallback(
149
-		callable $callBack,
150
-		string $pluginName,
151
-		string $eventName,
152
-	): callable {
153
-		$connection = \OCP\Server::get(Connection::class);
154
-		return function (PropFind $propFind, INode $node) use (
155
-			$callBack,
156
-			$pluginName,
157
-			$eventName,
158
-			$connection,
159
-		): bool {
160
-			$queriesBefore = $connection->getStats()['executed'];
161
-			$result = $callBack($propFind, $node);
162
-			$queriesAfter = $connection->getStats()['executed'];
163
-			$this->trackPluginQueries(
164
-				$pluginName,
165
-				$eventName,
166
-				$queriesAfter - $queriesBefore,
167
-				$propFind->getDepth()
168
-			);
169
-
170
-			// many callbacks don't care about returning a bool
171
-			return $result ?? true;
172
-		};
173
-	}
174
-
175
-	/**
176
-	 * Tracks the queries executed by a specific plugin.
177
-	 */
178
-	private function trackPluginQueries(
179
-		string $pluginName,
180
-		string $eventName,
181
-		int $queriesExecuted,
182
-		int $depth,
183
-	): void {
184
-		// report only nodes which cause queries to the DB
185
-		if ($queriesExecuted === 0) {
186
-			return;
187
-		}
188
-
189
-		$this->pluginQueries[$eventName][$depth][$pluginName]['nodes']
190
-			= ($this->pluginQueries[$eventName][$depth][$pluginName]['nodes'] ?? 0) + 1;
191
-
192
-		$this->pluginQueries[$eventName][$depth][$pluginName]['queries']
193
-			= ($this->pluginQueries[$eventName][$depth][$pluginName]['queries'] ?? 0) + $queriesExecuted;
194
-	}
195
-
196
-	/**
197
-	 *
198
-	 * @return void
199
-	 */
200
-	public function start() {
201
-		try {
202
-			// If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
203
-			// origin, we must make sure we send back HTTP/1.0 if this was
204
-			// requested.
205
-			// This is mainly because nginx doesn't support Chunked Transfer
206
-			// Encoding, and this forces the webserver SabreDAV is running on,
207
-			// to buffer entire responses to calculate Content-Length.
208
-			$this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion());
209
-
210
-			// Setting the base url
211
-			$this->httpRequest->setBaseUrl($this->getBaseUri());
212
-			$this->invokeMethod($this->httpRequest, $this->httpResponse);
213
-		} catch (\Throwable $e) {
214
-			try {
215
-				$this->emit('exception', [$e]);
216
-			} catch (\Exception) {
217
-			}
218
-
219
-			if ($e instanceof TypeError) {
220
-				/*
26
+    /** @var CachingTree $tree */
27
+
28
+    /**
29
+     * Tracks queries done by plugins.
30
+     * @var array<string, array<int, array<string, array{nodes:int,
31
+     *     queries:int}>>> The keys represent: event name, depth and plugin name
32
+     */
33
+    private array $pluginQueries = [];
34
+
35
+    public bool $debugEnabled = false;
36
+
37
+    /**
38
+     * @var array<string, array<int, callable>>
39
+     */
40
+    private array $originalListeners = [];
41
+
42
+    /**
43
+     * @var array<string, array<int, callable>>
44
+     */
45
+    private array $wrappedListeners = [];
46
+
47
+    /**
48
+     * @see \Sabre\DAV\Server
49
+     */
50
+    public function __construct($treeOrNode = null) {
51
+        parent::__construct($treeOrNode);
52
+        self::$exposeVersion = false;
53
+        $this->enablePropfindDepthInfinity = true;
54
+    }
55
+
56
+    #[Override]
57
+    public function once(
58
+        string $eventName,
59
+        callable $callBack,
60
+        int $priority = 100,
61
+    ): void {
62
+        $this->debugEnabled ? $this->monitorPropfindQueries(
63
+            parent::once(...),
64
+            ...\func_get_args(),
65
+        ) : parent::once(...\func_get_args());
66
+    }
67
+
68
+    #[Override]
69
+    public function on(
70
+        string $eventName,
71
+        callable $callBack,
72
+        int $priority = 100,
73
+    ): void {
74
+        $this->debugEnabled ? $this->monitorPropfindQueries(
75
+            parent::on(...),
76
+            ...\func_get_args(),
77
+        ) : parent::on(...\func_get_args());
78
+    }
79
+
80
+    /**
81
+     * Wraps the handler $callBack into a query-monitoring function and calls
82
+     * $parentFn to register it.
83
+     */
84
+    private function monitorPropfindQueries(
85
+        callable $parentFn,
86
+        string $eventName,
87
+        callable $callBack,
88
+        int $priority = 100,
89
+    ): void {
90
+        $pluginName = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['class'] ?? 'unknown';
91
+        // The NotifyPlugin needs to be excluded as it emits the
92
+        // `preloadCollection` event, which causes many plugins run queries.
93
+        /** @psalm-suppress TypeDoesNotContainType */
94
+        if ($pluginName === PropFindPreloadNotifyPlugin::class || ($eventName !== 'propFind'
95
+                && $eventName !== 'preloadCollection')) {
96
+            $parentFn($eventName, $callBack, $priority);
97
+            return;
98
+        }
99
+
100
+        $wrappedCallback
101
+            = $this->getMonitoredCallback($callBack, $pluginName, $eventName);
102
+        $this->originalListeners[$eventName][] = $callBack;
103
+        $this->wrappedListeners[$eventName][] = $wrappedCallback;
104
+
105
+        $parentFn($eventName, $wrappedCallback, $priority);
106
+    }
107
+
108
+    public function removeListener(
109
+        string $eventName,
110
+        callable $listener,
111
+    ): bool {
112
+        $listenerIndex = null;
113
+        if (isset($this->wrappedListeners[$eventName], $this->originalListeners[$eventName])) {
114
+            $key = array_search(
115
+                $listener,
116
+                $this->originalListeners[$eventName],
117
+                true
118
+            );
119
+            if ($key !== false) {
120
+                $listenerIndex = $key;
121
+                $listener = $this->wrappedListeners[$eventName][$listenerIndex];
122
+            }
123
+        }
124
+        $removed = parent::removeListener($eventName, $listener);
125
+
126
+        if ($removed && $listenerIndex !== null) {
127
+            unset($this->originalListeners[$eventName][$listenerIndex], $this->wrappedListeners[$eventName][$listenerIndex]);
128
+        }
129
+
130
+        return $removed;
131
+    }
132
+
133
+    public function removeAllListeners(?string $eventName = null): void {
134
+        parent::removeAllListeners($eventName);
135
+
136
+        if ($eventName === null) {
137
+            $this->originalListeners = [];
138
+            $this->wrappedListeners = [];
139
+        } else {
140
+            unset($this->wrappedListeners[$eventName], $this->originalListeners[$eventName]);
141
+        }
142
+    }
143
+
144
+    /**
145
+     * Returns a callable that wraps $callBack with code that monitors and
146
+     * records queries per plugin.
147
+     */
148
+    private function getMonitoredCallback(
149
+        callable $callBack,
150
+        string $pluginName,
151
+        string $eventName,
152
+    ): callable {
153
+        $connection = \OCP\Server::get(Connection::class);
154
+        return function (PropFind $propFind, INode $node) use (
155
+            $callBack,
156
+            $pluginName,
157
+            $eventName,
158
+            $connection,
159
+        ): bool {
160
+            $queriesBefore = $connection->getStats()['executed'];
161
+            $result = $callBack($propFind, $node);
162
+            $queriesAfter = $connection->getStats()['executed'];
163
+            $this->trackPluginQueries(
164
+                $pluginName,
165
+                $eventName,
166
+                $queriesAfter - $queriesBefore,
167
+                $propFind->getDepth()
168
+            );
169
+
170
+            // many callbacks don't care about returning a bool
171
+            return $result ?? true;
172
+        };
173
+    }
174
+
175
+    /**
176
+     * Tracks the queries executed by a specific plugin.
177
+     */
178
+    private function trackPluginQueries(
179
+        string $pluginName,
180
+        string $eventName,
181
+        int $queriesExecuted,
182
+        int $depth,
183
+    ): void {
184
+        // report only nodes which cause queries to the DB
185
+        if ($queriesExecuted === 0) {
186
+            return;
187
+        }
188
+
189
+        $this->pluginQueries[$eventName][$depth][$pluginName]['nodes']
190
+            = ($this->pluginQueries[$eventName][$depth][$pluginName]['nodes'] ?? 0) + 1;
191
+
192
+        $this->pluginQueries[$eventName][$depth][$pluginName]['queries']
193
+            = ($this->pluginQueries[$eventName][$depth][$pluginName]['queries'] ?? 0) + $queriesExecuted;
194
+    }
195
+
196
+    /**
197
+     *
198
+     * @return void
199
+     */
200
+    public function start() {
201
+        try {
202
+            // If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
203
+            // origin, we must make sure we send back HTTP/1.0 if this was
204
+            // requested.
205
+            // This is mainly because nginx doesn't support Chunked Transfer
206
+            // Encoding, and this forces the webserver SabreDAV is running on,
207
+            // to buffer entire responses to calculate Content-Length.
208
+            $this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion());
209
+
210
+            // Setting the base url
211
+            $this->httpRequest->setBaseUrl($this->getBaseUri());
212
+            $this->invokeMethod($this->httpRequest, $this->httpResponse);
213
+        } catch (\Throwable $e) {
214
+            try {
215
+                $this->emit('exception', [$e]);
216
+            } catch (\Exception) {
217
+            }
218
+
219
+            if ($e instanceof TypeError) {
220
+                /*
221 221
 				 * The TypeError includes the file path where the error occurred,
222 222
 				 * potentially revealing the installation directory.
223 223
 				 */
224
-				$e = new TypeError('A type error occurred. For more details, please refer to the logs, which provide additional context about the type error.');
225
-			}
226
-
227
-			$DOM = new \DOMDocument('1.0', 'utf-8');
228
-			$DOM->formatOutput = true;
229
-
230
-			$error = $DOM->createElementNS('DAV:', 'd:error');
231
-			$error->setAttribute('xmlns:s', self::NS_SABREDAV);
232
-			$DOM->appendChild($error);
233
-
234
-			$h = function ($v) {
235
-				return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
236
-			};
237
-
238
-			if (self::$exposeVersion) {
239
-				$error->appendChild($DOM->createElement('s:sabredav-version', $h(Version::VERSION)));
240
-			}
241
-
242
-			$error->appendChild($DOM->createElement('s:exception', $h(get_class($e))));
243
-			$error->appendChild($DOM->createElement('s:message', $h($e->getMessage())));
244
-			if ($this->debugExceptions) {
245
-				$error->appendChild($DOM->createElement('s:file', $h($e->getFile())));
246
-				$error->appendChild($DOM->createElement('s:line', $h($e->getLine())));
247
-				$error->appendChild($DOM->createElement('s:code', $h($e->getCode())));
248
-				$error->appendChild($DOM->createElement('s:stacktrace', $h($e->getTraceAsString())));
249
-			}
250
-
251
-			if ($this->debugExceptions) {
252
-				$previous = $e;
253
-				while ($previous = $previous->getPrevious()) {
254
-					$xPrevious = $DOM->createElement('s:previous-exception');
255
-					$xPrevious->appendChild($DOM->createElement('s:exception', $h(get_class($previous))));
256
-					$xPrevious->appendChild($DOM->createElement('s:message', $h($previous->getMessage())));
257
-					$xPrevious->appendChild($DOM->createElement('s:file', $h($previous->getFile())));
258
-					$xPrevious->appendChild($DOM->createElement('s:line', $h($previous->getLine())));
259
-					$xPrevious->appendChild($DOM->createElement('s:code', $h($previous->getCode())));
260
-					$xPrevious->appendChild($DOM->createElement('s:stacktrace', $h($previous->getTraceAsString())));
261
-					$error->appendChild($xPrevious);
262
-				}
263
-			}
264
-
265
-			if ($e instanceof Exception) {
266
-				$httpCode = $e->getHTTPCode();
267
-				$e->serialize($this, $error);
268
-				$headers = $e->getHTTPHeaders($this);
269
-			} else {
270
-				$httpCode = 500;
271
-				$headers = [];
272
-			}
273
-			$headers['Content-Type'] = 'application/xml; charset=utf-8';
274
-
275
-			$this->httpResponse->setStatus($httpCode);
276
-			$this->httpResponse->setHeaders($headers);
277
-			$this->httpResponse->setBody($DOM->saveXML());
278
-			$this->sapi->sendResponse($this->httpResponse);
279
-		}
280
-	}
281
-
282
-	/**
283
-	 * Returns queries executed by registered plugins.
284
-	 * @return array<string, array<int, array<string, array{nodes:int,
285
-	 *     queries:int}>>> The keys represent: event name, depth and plugin name
286
-	 */
287
-	public function getPluginQueries(): array {
288
-		return $this->pluginQueries;
289
-	}
224
+                $e = new TypeError('A type error occurred. For more details, please refer to the logs, which provide additional context about the type error.');
225
+            }
226
+
227
+            $DOM = new \DOMDocument('1.0', 'utf-8');
228
+            $DOM->formatOutput = true;
229
+
230
+            $error = $DOM->createElementNS('DAV:', 'd:error');
231
+            $error->setAttribute('xmlns:s', self::NS_SABREDAV);
232
+            $DOM->appendChild($error);
233
+
234
+            $h = function ($v) {
235
+                return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
236
+            };
237
+
238
+            if (self::$exposeVersion) {
239
+                $error->appendChild($DOM->createElement('s:sabredav-version', $h(Version::VERSION)));
240
+            }
241
+
242
+            $error->appendChild($DOM->createElement('s:exception', $h(get_class($e))));
243
+            $error->appendChild($DOM->createElement('s:message', $h($e->getMessage())));
244
+            if ($this->debugExceptions) {
245
+                $error->appendChild($DOM->createElement('s:file', $h($e->getFile())));
246
+                $error->appendChild($DOM->createElement('s:line', $h($e->getLine())));
247
+                $error->appendChild($DOM->createElement('s:code', $h($e->getCode())));
248
+                $error->appendChild($DOM->createElement('s:stacktrace', $h($e->getTraceAsString())));
249
+            }
250
+
251
+            if ($this->debugExceptions) {
252
+                $previous = $e;
253
+                while ($previous = $previous->getPrevious()) {
254
+                    $xPrevious = $DOM->createElement('s:previous-exception');
255
+                    $xPrevious->appendChild($DOM->createElement('s:exception', $h(get_class($previous))));
256
+                    $xPrevious->appendChild($DOM->createElement('s:message', $h($previous->getMessage())));
257
+                    $xPrevious->appendChild($DOM->createElement('s:file', $h($previous->getFile())));
258
+                    $xPrevious->appendChild($DOM->createElement('s:line', $h($previous->getLine())));
259
+                    $xPrevious->appendChild($DOM->createElement('s:code', $h($previous->getCode())));
260
+                    $xPrevious->appendChild($DOM->createElement('s:stacktrace', $h($previous->getTraceAsString())));
261
+                    $error->appendChild($xPrevious);
262
+                }
263
+            }
264
+
265
+            if ($e instanceof Exception) {
266
+                $httpCode = $e->getHTTPCode();
267
+                $e->serialize($this, $error);
268
+                $headers = $e->getHTTPHeaders($this);
269
+            } else {
270
+                $httpCode = 500;
271
+                $headers = [];
272
+            }
273
+            $headers['Content-Type'] = 'application/xml; charset=utf-8';
274
+
275
+            $this->httpResponse->setStatus($httpCode);
276
+            $this->httpResponse->setHeaders($headers);
277
+            $this->httpResponse->setBody($DOM->saveXML());
278
+            $this->sapi->sendResponse($this->httpResponse);
279
+        }
280
+    }
281
+
282
+    /**
283
+     * Returns queries executed by registered plugins.
284
+     * @return array<string, array<int, array<string, array{nodes:int,
285
+     *     queries:int}>>> The keys represent: event name, depth and plugin name
286
+     */
287
+    public function getPluginQueries(): array {
288
+        return $this->pluginQueries;
289
+    }
290 290
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 		string $eventName,
152 152
 	): callable {
153 153
 		$connection = \OCP\Server::get(Connection::class);
154
-		return function (PropFind $propFind, INode $node) use (
154
+		return function(PropFind $propFind, INode $node) use (
155 155
 			$callBack,
156 156
 			$pluginName,
157 157
 			$eventName,
@@ -231,8 +231,8 @@  discard block
 block discarded – undo
231 231
 			$error->setAttribute('xmlns:s', self::NS_SABREDAV);
232 232
 			$DOM->appendChild($error);
233 233
 
234
-			$h = function ($v) {
235
-				return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
234
+			$h = function($v) {
235
+				return htmlspecialchars((string) $v, ENT_NOQUOTES, 'UTF-8');
236 236
 			};
237 237
 
238 238
 			if (self::$exposeVersion) {
Please login to merge, or discard this patch.