Completed
Push — master ( 1f2409...50c9c7 )
by
unknown
22:17 queued 14s
created
apps/dav/lib/Connector/Sabre/Server.php 1 patch
Indentation   +201 added lines, -201 removed lines patch added patch discarded remove patch
@@ -23,208 +23,208 @@
 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<int, array<string, array{nodes:int, queries:int}>>
31
-	 */
32
-	private array $pluginQueries = [];
33
-
34
-	public bool $debugEnabled = false;
35
-
36
-	/**
37
-	 * @see \Sabre\DAV\Server
38
-	 */
39
-	public function __construct($treeOrNode = null) {
40
-		parent::__construct($treeOrNode);
41
-		self::$exposeVersion = false;
42
-		$this->enablePropfindDepthInfinity = true;
43
-	}
44
-
45
-	#[Override]
46
-	public function once(
47
-		string $eventName,
48
-		callable $callBack,
49
-		int $priority = 100,
50
-	): void {
51
-		$this->debugEnabled ? $this->monitorPropfindQueries(
52
-			parent::once(...),
53
-			...func_get_args(),
54
-		) : parent::once(...func_get_args());
55
-	}
56
-
57
-	#[Override]
58
-	public function on(
59
-		string $eventName,
60
-		callable $callBack,
61
-		int $priority = 100,
62
-	): void {
63
-		$this->debugEnabled ? $this->monitorPropfindQueries(
64
-			parent::on(...),
65
-			...func_get_args(),
66
-		) : parent::on(...func_get_args());
67
-	}
68
-
69
-	/**
70
-	 * Wraps the handler $callBack into a query-monitoring function and calls
71
-	 * $parentFn to register it.
72
-	 */
73
-	private function monitorPropfindQueries(
74
-		callable $parentFn,
75
-		string $eventName,
76
-		callable $callBack,
77
-		int $priority = 100,
78
-	): void {
79
-		if ($eventName !== 'propFind') {
80
-			$parentFn($eventName, $callBack, $priority);
81
-			return;
82
-		}
83
-
84
-		$pluginName = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['class'] ?? 'unknown';
85
-		$callback = $this->getMonitoredCallback($callBack, $pluginName);
86
-
87
-		$parentFn($eventName, $callback, $priority);
88
-	}
89
-
90
-	/**
91
-	 * Returns a callable that wraps $callBack with code that monitors and
92
-	 * records queries per plugin.
93
-	 */
94
-	private function getMonitoredCallback(
95
-		callable $callBack,
96
-		string $pluginName,
97
-	): callable {
98
-		return function (PropFind $propFind, INode $node) use (
99
-			$callBack,
100
-			$pluginName,
101
-		) {
102
-			$connection = \OCP\Server::get(Connection::class);
103
-			$queriesBefore = $connection->getStats()['executed'];
104
-			$result = $callBack($propFind, $node);
105
-			$queriesAfter = $connection->getStats()['executed'];
106
-			$this->trackPluginQueries(
107
-				$pluginName,
108
-				$queriesAfter - $queriesBefore,
109
-				$propFind->getDepth()
110
-			);
111
-
112
-			return $result;
113
-		};
114
-	}
115
-
116
-	/**
117
-	 * Tracks the queries executed by a specific plugin.
118
-	 */
119
-	private function trackPluginQueries(
120
-		string $pluginName,
121
-		int $queriesExecuted,
122
-		int $depth,
123
-	): void {
124
-		// report only nodes which cause queries to the DB
125
-		if ($queriesExecuted === 0) {
126
-			return;
127
-		}
128
-
129
-		$this->pluginQueries[$depth][$pluginName]['nodes']
130
-			= ($this->pluginQueries[$depth][$pluginName]['nodes'] ?? 0) + 1;
131
-
132
-		$this->pluginQueries[$depth][$pluginName]['queries']
133
-			= ($this->pluginQueries[$depth][$pluginName]['queries'] ?? 0) + $queriesExecuted;
134
-	}
135
-
136
-	/**
137
-	 *
138
-	 * @return void
139
-	 */
140
-	public function start() {
141
-		try {
142
-			// If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
143
-			// origin, we must make sure we send back HTTP/1.0 if this was
144
-			// requested.
145
-			// This is mainly because nginx doesn't support Chunked Transfer
146
-			// Encoding, and this forces the webserver SabreDAV is running on,
147
-			// to buffer entire responses to calculate Content-Length.
148
-			$this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion());
149
-
150
-			// Setting the base url
151
-			$this->httpRequest->setBaseUrl($this->getBaseUri());
152
-			$this->invokeMethod($this->httpRequest, $this->httpResponse);
153
-		} catch (\Throwable $e) {
154
-			try {
155
-				$this->emit('exception', [$e]);
156
-			} catch (\Exception) {
157
-			}
158
-
159
-			if ($e instanceof TypeError) {
160
-				/*
26
+    /** @var CachingTree $tree */
27
+
28
+    /**
29
+     * Tracks queries done by plugins.
30
+     * @var array<int, array<string, array{nodes:int, queries:int}>>
31
+     */
32
+    private array $pluginQueries = [];
33
+
34
+    public bool $debugEnabled = false;
35
+
36
+    /**
37
+     * @see \Sabre\DAV\Server
38
+     */
39
+    public function __construct($treeOrNode = null) {
40
+        parent::__construct($treeOrNode);
41
+        self::$exposeVersion = false;
42
+        $this->enablePropfindDepthInfinity = true;
43
+    }
44
+
45
+    #[Override]
46
+    public function once(
47
+        string $eventName,
48
+        callable $callBack,
49
+        int $priority = 100,
50
+    ): void {
51
+        $this->debugEnabled ? $this->monitorPropfindQueries(
52
+            parent::once(...),
53
+            ...func_get_args(),
54
+        ) : parent::once(...func_get_args());
55
+    }
56
+
57
+    #[Override]
58
+    public function on(
59
+        string $eventName,
60
+        callable $callBack,
61
+        int $priority = 100,
62
+    ): void {
63
+        $this->debugEnabled ? $this->monitorPropfindQueries(
64
+            parent::on(...),
65
+            ...func_get_args(),
66
+        ) : parent::on(...func_get_args());
67
+    }
68
+
69
+    /**
70
+     * Wraps the handler $callBack into a query-monitoring function and calls
71
+     * $parentFn to register it.
72
+     */
73
+    private function monitorPropfindQueries(
74
+        callable $parentFn,
75
+        string $eventName,
76
+        callable $callBack,
77
+        int $priority = 100,
78
+    ): void {
79
+        if ($eventName !== 'propFind') {
80
+            $parentFn($eventName, $callBack, $priority);
81
+            return;
82
+        }
83
+
84
+        $pluginName = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['class'] ?? 'unknown';
85
+        $callback = $this->getMonitoredCallback($callBack, $pluginName);
86
+
87
+        $parentFn($eventName, $callback, $priority);
88
+    }
89
+
90
+    /**
91
+     * Returns a callable that wraps $callBack with code that monitors and
92
+     * records queries per plugin.
93
+     */
94
+    private function getMonitoredCallback(
95
+        callable $callBack,
96
+        string $pluginName,
97
+    ): callable {
98
+        return function (PropFind $propFind, INode $node) use (
99
+            $callBack,
100
+            $pluginName,
101
+        ) {
102
+            $connection = \OCP\Server::get(Connection::class);
103
+            $queriesBefore = $connection->getStats()['executed'];
104
+            $result = $callBack($propFind, $node);
105
+            $queriesAfter = $connection->getStats()['executed'];
106
+            $this->trackPluginQueries(
107
+                $pluginName,
108
+                $queriesAfter - $queriesBefore,
109
+                $propFind->getDepth()
110
+            );
111
+
112
+            return $result;
113
+        };
114
+    }
115
+
116
+    /**
117
+     * Tracks the queries executed by a specific plugin.
118
+     */
119
+    private function trackPluginQueries(
120
+        string $pluginName,
121
+        int $queriesExecuted,
122
+        int $depth,
123
+    ): void {
124
+        // report only nodes which cause queries to the DB
125
+        if ($queriesExecuted === 0) {
126
+            return;
127
+        }
128
+
129
+        $this->pluginQueries[$depth][$pluginName]['nodes']
130
+            = ($this->pluginQueries[$depth][$pluginName]['nodes'] ?? 0) + 1;
131
+
132
+        $this->pluginQueries[$depth][$pluginName]['queries']
133
+            = ($this->pluginQueries[$depth][$pluginName]['queries'] ?? 0) + $queriesExecuted;
134
+    }
135
+
136
+    /**
137
+     *
138
+     * @return void
139
+     */
140
+    public function start() {
141
+        try {
142
+            // If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
143
+            // origin, we must make sure we send back HTTP/1.0 if this was
144
+            // requested.
145
+            // This is mainly because nginx doesn't support Chunked Transfer
146
+            // Encoding, and this forces the webserver SabreDAV is running on,
147
+            // to buffer entire responses to calculate Content-Length.
148
+            $this->httpResponse->setHTTPVersion($this->httpRequest->getHTTPVersion());
149
+
150
+            // Setting the base url
151
+            $this->httpRequest->setBaseUrl($this->getBaseUri());
152
+            $this->invokeMethod($this->httpRequest, $this->httpResponse);
153
+        } catch (\Throwable $e) {
154
+            try {
155
+                $this->emit('exception', [$e]);
156
+            } catch (\Exception) {
157
+            }
158
+
159
+            if ($e instanceof TypeError) {
160
+                /*
161 161
 				 * The TypeError includes the file path where the error occurred,
162 162
 				 * potentially revealing the installation directory.
163 163
 				 */
164
-				$e = new TypeError('A type error occurred. For more details, please refer to the logs, which provide additional context about the type error.');
165
-			}
166
-
167
-			$DOM = new \DOMDocument('1.0', 'utf-8');
168
-			$DOM->formatOutput = true;
169
-
170
-			$error = $DOM->createElementNS('DAV:', 'd:error');
171
-			$error->setAttribute('xmlns:s', self::NS_SABREDAV);
172
-			$DOM->appendChild($error);
173
-
174
-			$h = function ($v) {
175
-				return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
176
-			};
177
-
178
-			if (self::$exposeVersion) {
179
-				$error->appendChild($DOM->createElement('s:sabredav-version', $h(Version::VERSION)));
180
-			}
181
-
182
-			$error->appendChild($DOM->createElement('s:exception', $h(get_class($e))));
183
-			$error->appendChild($DOM->createElement('s:message', $h($e->getMessage())));
184
-			if ($this->debugExceptions) {
185
-				$error->appendChild($DOM->createElement('s:file', $h($e->getFile())));
186
-				$error->appendChild($DOM->createElement('s:line', $h($e->getLine())));
187
-				$error->appendChild($DOM->createElement('s:code', $h($e->getCode())));
188
-				$error->appendChild($DOM->createElement('s:stacktrace', $h($e->getTraceAsString())));
189
-			}
190
-
191
-			if ($this->debugExceptions) {
192
-				$previous = $e;
193
-				while ($previous = $previous->getPrevious()) {
194
-					$xPrevious = $DOM->createElement('s:previous-exception');
195
-					$xPrevious->appendChild($DOM->createElement('s:exception', $h(get_class($previous))));
196
-					$xPrevious->appendChild($DOM->createElement('s:message', $h($previous->getMessage())));
197
-					$xPrevious->appendChild($DOM->createElement('s:file', $h($previous->getFile())));
198
-					$xPrevious->appendChild($DOM->createElement('s:line', $h($previous->getLine())));
199
-					$xPrevious->appendChild($DOM->createElement('s:code', $h($previous->getCode())));
200
-					$xPrevious->appendChild($DOM->createElement('s:stacktrace', $h($previous->getTraceAsString())));
201
-					$error->appendChild($xPrevious);
202
-				}
203
-			}
204
-
205
-			if ($e instanceof Exception) {
206
-				$httpCode = $e->getHTTPCode();
207
-				$e->serialize($this, $error);
208
-				$headers = $e->getHTTPHeaders($this);
209
-			} else {
210
-				$httpCode = 500;
211
-				$headers = [];
212
-			}
213
-			$headers['Content-Type'] = 'application/xml; charset=utf-8';
214
-
215
-			$this->httpResponse->setStatus($httpCode);
216
-			$this->httpResponse->setHeaders($headers);
217
-			$this->httpResponse->setBody($DOM->saveXML());
218
-			$this->sapi->sendResponse($this->httpResponse);
219
-		}
220
-	}
221
-
222
-	/**
223
-	 * Returns queries executed by registered plugins.
224
-	 *
225
-	 * @return array<int, array<string, array{nodes:int, queries:int}>>
226
-	 */
227
-	public function getPluginQueries(): array {
228
-		return $this->pluginQueries;
229
-	}
164
+                $e = new TypeError('A type error occurred. For more details, please refer to the logs, which provide additional context about the type error.');
165
+            }
166
+
167
+            $DOM = new \DOMDocument('1.0', 'utf-8');
168
+            $DOM->formatOutput = true;
169
+
170
+            $error = $DOM->createElementNS('DAV:', 'd:error');
171
+            $error->setAttribute('xmlns:s', self::NS_SABREDAV);
172
+            $DOM->appendChild($error);
173
+
174
+            $h = function ($v) {
175
+                return htmlspecialchars((string)$v, ENT_NOQUOTES, 'UTF-8');
176
+            };
177
+
178
+            if (self::$exposeVersion) {
179
+                $error->appendChild($DOM->createElement('s:sabredav-version', $h(Version::VERSION)));
180
+            }
181
+
182
+            $error->appendChild($DOM->createElement('s:exception', $h(get_class($e))));
183
+            $error->appendChild($DOM->createElement('s:message', $h($e->getMessage())));
184
+            if ($this->debugExceptions) {
185
+                $error->appendChild($DOM->createElement('s:file', $h($e->getFile())));
186
+                $error->appendChild($DOM->createElement('s:line', $h($e->getLine())));
187
+                $error->appendChild($DOM->createElement('s:code', $h($e->getCode())));
188
+                $error->appendChild($DOM->createElement('s:stacktrace', $h($e->getTraceAsString())));
189
+            }
190
+
191
+            if ($this->debugExceptions) {
192
+                $previous = $e;
193
+                while ($previous = $previous->getPrevious()) {
194
+                    $xPrevious = $DOM->createElement('s:previous-exception');
195
+                    $xPrevious->appendChild($DOM->createElement('s:exception', $h(get_class($previous))));
196
+                    $xPrevious->appendChild($DOM->createElement('s:message', $h($previous->getMessage())));
197
+                    $xPrevious->appendChild($DOM->createElement('s:file', $h($previous->getFile())));
198
+                    $xPrevious->appendChild($DOM->createElement('s:line', $h($previous->getLine())));
199
+                    $xPrevious->appendChild($DOM->createElement('s:code', $h($previous->getCode())));
200
+                    $xPrevious->appendChild($DOM->createElement('s:stacktrace', $h($previous->getTraceAsString())));
201
+                    $error->appendChild($xPrevious);
202
+                }
203
+            }
204
+
205
+            if ($e instanceof Exception) {
206
+                $httpCode = $e->getHTTPCode();
207
+                $e->serialize($this, $error);
208
+                $headers = $e->getHTTPHeaders($this);
209
+            } else {
210
+                $httpCode = 500;
211
+                $headers = [];
212
+            }
213
+            $headers['Content-Type'] = 'application/xml; charset=utf-8';
214
+
215
+            $this->httpResponse->setStatus($httpCode);
216
+            $this->httpResponse->setHeaders($headers);
217
+            $this->httpResponse->setBody($DOM->saveXML());
218
+            $this->sapi->sendResponse($this->httpResponse);
219
+        }
220
+    }
221
+
222
+    /**
223
+     * Returns queries executed by registered plugins.
224
+     *
225
+     * @return array<int, array<string, array{nodes:int, queries:int}>>
226
+     */
227
+    public function getPluginQueries(): array {
228
+        return $this->pluginQueries;
229
+    }
230 230
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/ServerFactory.php 1 patch
Indentation   +202 added lines, -202 removed lines patch added patch discarded remove patch
@@ -44,206 +44,206 @@
 block discarded – undo
44 44
 
45 45
 class ServerFactory {
46 46
 
47
-	public function __construct(
48
-		private IConfig $config,
49
-		private LoggerInterface $logger,
50
-		private IDBConnection $databaseConnection,
51
-		private IUserSession $userSession,
52
-		private IMountManager $mountManager,
53
-		private ITagManager $tagManager,
54
-		private IRequest $request,
55
-		private IPreview $previewManager,
56
-		private IEventDispatcher $eventDispatcher,
57
-		private IL10N $l10n,
58
-	) {
59
-	}
60
-
61
-	/**
62
-	 * @param callable $viewCallBack callback that should return the view for the dav endpoint
63
-	 */
64
-	public function createServer(
65
-		bool $isPublicShare,
66
-		string $baseUri,
67
-		string $requestUri,
68
-		Plugin $authPlugin,
69
-		callable $viewCallBack,
70
-	): Server {
71
-		$debugEnabled = $this->config->getSystemValue('debug', false);
72
-		// Fire up server
73
-		if ($isPublicShare) {
74
-			$rootCollection = new SimpleCollection('root');
75
-			$tree = new CachingTree($rootCollection);
76
-		} else {
77
-			$rootCollection = null;
78
-			$tree = new ObjectTree();
79
-		}
80
-		$server = new Server($tree);
81
-		// Set URL explicitly due to reverse-proxy situations
82
-		$server->httpRequest->setUrl($requestUri);
83
-		$server->setBaseUri($baseUri);
84
-
85
-		// Load plugins
86
-		$server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
87
-		$server->addPlugin(new BlockLegacyClientPlugin(
88
-			$this->config,
89
-			\OCP\Server::get(ThemingDefaults::class),
90
-		));
91
-		$server->addPlugin(new AnonymousOptionsPlugin());
92
-		$server->addPlugin($authPlugin);
93
-		if ($debugEnabled) {
94
-			$server->debugEnabled = $debugEnabled;
95
-			$server->addPlugin(new PropFindMonitorPlugin());
96
-		}
97
-		// FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
98
-		$server->addPlugin(new DummyGetResponsePlugin());
99
-		$server->addPlugin(new ExceptionLoggerPlugin('webdav', $this->logger));
100
-		$server->addPlugin(new LockPlugin());
101
-
102
-		$server->addPlugin(new RequestIdHeaderPlugin($this->request));
103
-
104
-		$server->addPlugin(new ZipFolderPlugin(
105
-			$tree,
106
-			$this->logger,
107
-			$this->eventDispatcher,
108
-		));
109
-
110
-		// Some WebDAV clients do require Class 2 WebDAV support (locking), since
111
-		// we do not provide locking we emulate it using a fake locking plugin.
112
-		if ($this->request->isUserAgent([
113
-			'/WebDAVFS/',
114
-			'/OneNote/',
115
-			'/Microsoft-WebDAV-MiniRedir/',
116
-		])) {
117
-			$server->addPlugin(new FakeLockerPlugin());
118
-		}
119
-
120
-		if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
121
-			$server->addPlugin(new BrowserErrorPagePlugin());
122
-		}
123
-
124
-		// wait with registering these until auth is handled and the filesystem is setup
125
-		$server->on('beforeMethod:*', function () use ($server, $tree,
126
-			$viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
127
-			// ensure the skeleton is copied
128
-			$userFolder = \OC::$server->getUserFolder();
129
-
130
-			/** @var View $view */
131
-			$view = $viewCallBack($server);
132
-			if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
133
-				$rootInfo = $userFolder;
134
-			} else {
135
-				$rootInfo = $view->getFileInfo('');
136
-			}
137
-
138
-			// Create Nextcloud Dir
139
-			if ($rootInfo->getType() === 'dir') {
140
-				$root = new Directory($view, $rootInfo, $tree);
141
-			} else {
142
-				$root = new File($view, $rootInfo);
143
-			}
144
-
145
-			if ($isPublicShare) {
146
-				$userPrincipalBackend = new Principal(
147
-					\OCP\Server::get(IUserManager::class),
148
-					\OCP\Server::get(IGroupManager::class),
149
-					\OCP\Server::get(IAccountManager::class),
150
-					\OCP\Server::get(\OCP\Share\IManager::class),
151
-					\OCP\Server::get(IUserSession::class),
152
-					\OCP\Server::get(IAppManager::class),
153
-					\OCP\Server::get(ProxyMapper::class),
154
-					\OCP\Server::get(KnownUserService::class),
155
-					\OCP\Server::get(IConfig::class),
156
-					\OC::$server->getL10NFactory(),
157
-				);
158
-
159
-				// Mount the share collection at /public.php/dav/shares/<share token>
160
-				$rootCollection->addChild(new RootCollection(
161
-					$root,
162
-					$userPrincipalBackend,
163
-					'principals/shares',
164
-				));
165
-
166
-				// Mount the upload collection at /public.php/dav/uploads/<share token>
167
-				$rootCollection->addChild(new \OCA\DAV\Upload\RootCollection(
168
-					$userPrincipalBackend,
169
-					'principals/shares',
170
-					\OCP\Server::get(CleanupService::class),
171
-					\OCP\Server::get(IRootFolder::class),
172
-					\OCP\Server::get(IUserSession::class),
173
-					\OCP\Server::get(\OCP\Share\IManager::class),
174
-				));
175
-			} else {
176
-				/** @var ObjectTree $tree */
177
-				$tree->init($root, $view, $this->mountManager);
178
-			}
179
-
180
-			$server->addPlugin(
181
-				new FilesPlugin(
182
-					$tree,
183
-					$this->config,
184
-					$this->request,
185
-					$this->previewManager,
186
-					$this->userSession,
187
-					\OCP\Server::get(IFilenameValidator::class),
188
-					\OCP\Server::get(IAccountManager::class),
189
-					false,
190
-					!$debugEnabled
191
-				)
192
-			);
193
-			$server->addPlugin(new QuotaPlugin($view));
194
-			$server->addPlugin(new ChecksumUpdatePlugin());
195
-
196
-			// Allow view-only plugin for webdav requests
197
-			$server->addPlugin(new ViewOnlyPlugin(
198
-				$userFolder,
199
-			));
200
-
201
-			if ($this->userSession->isLoggedIn()) {
202
-				$server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
203
-				$server->addPlugin(new SharesPlugin(
204
-					$tree,
205
-					$this->userSession,
206
-					$userFolder,
207
-					\OCP\Server::get(\OCP\Share\IManager::class)
208
-				));
209
-				$server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
210
-				$server->addPlugin(new FilesReportPlugin(
211
-					$tree,
212
-					$view,
213
-					\OCP\Server::get(ISystemTagManager::class),
214
-					\OCP\Server::get(ISystemTagObjectMapper::class),
215
-					\OCP\Server::get(ITagManager::class),
216
-					$this->userSession,
217
-					\OCP\Server::get(IGroupManager::class),
218
-					$userFolder,
219
-					\OCP\Server::get(IAppManager::class)
220
-				));
221
-				// custom properties plugin must be the last one
222
-				$server->addPlugin(
223
-					new \Sabre\DAV\PropertyStorage\Plugin(
224
-						new CustomPropertiesBackend(
225
-							$server,
226
-							$tree,
227
-							$this->databaseConnection,
228
-							$this->userSession->getUser(),
229
-							\OCP\Server::get(DefaultCalendarValidator::class),
230
-						)
231
-					)
232
-				);
233
-			}
234
-			$server->addPlugin(new CopyEtagHeaderPlugin());
235
-
236
-			// Load dav plugins from apps
237
-			$event = new SabrePluginEvent($server);
238
-			$this->eventDispatcher->dispatchTyped($event);
239
-			$pluginManager = new PluginManager(
240
-				\OC::$server,
241
-				\OCP\Server::get(IAppManager::class)
242
-			);
243
-			foreach ($pluginManager->getAppPlugins() as $appPlugin) {
244
-				$server->addPlugin($appPlugin);
245
-			}
246
-		}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
247
-		return $server;
248
-	}
47
+    public function __construct(
48
+        private IConfig $config,
49
+        private LoggerInterface $logger,
50
+        private IDBConnection $databaseConnection,
51
+        private IUserSession $userSession,
52
+        private IMountManager $mountManager,
53
+        private ITagManager $tagManager,
54
+        private IRequest $request,
55
+        private IPreview $previewManager,
56
+        private IEventDispatcher $eventDispatcher,
57
+        private IL10N $l10n,
58
+    ) {
59
+    }
60
+
61
+    /**
62
+     * @param callable $viewCallBack callback that should return the view for the dav endpoint
63
+     */
64
+    public function createServer(
65
+        bool $isPublicShare,
66
+        string $baseUri,
67
+        string $requestUri,
68
+        Plugin $authPlugin,
69
+        callable $viewCallBack,
70
+    ): Server {
71
+        $debugEnabled = $this->config->getSystemValue('debug', false);
72
+        // Fire up server
73
+        if ($isPublicShare) {
74
+            $rootCollection = new SimpleCollection('root');
75
+            $tree = new CachingTree($rootCollection);
76
+        } else {
77
+            $rootCollection = null;
78
+            $tree = new ObjectTree();
79
+        }
80
+        $server = new Server($tree);
81
+        // Set URL explicitly due to reverse-proxy situations
82
+        $server->httpRequest->setUrl($requestUri);
83
+        $server->setBaseUri($baseUri);
84
+
85
+        // Load plugins
86
+        $server->addPlugin(new MaintenancePlugin($this->config, $this->l10n));
87
+        $server->addPlugin(new BlockLegacyClientPlugin(
88
+            $this->config,
89
+            \OCP\Server::get(ThemingDefaults::class),
90
+        ));
91
+        $server->addPlugin(new AnonymousOptionsPlugin());
92
+        $server->addPlugin($authPlugin);
93
+        if ($debugEnabled) {
94
+            $server->debugEnabled = $debugEnabled;
95
+            $server->addPlugin(new PropFindMonitorPlugin());
96
+        }
97
+        // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to /
98
+        $server->addPlugin(new DummyGetResponsePlugin());
99
+        $server->addPlugin(new ExceptionLoggerPlugin('webdav', $this->logger));
100
+        $server->addPlugin(new LockPlugin());
101
+
102
+        $server->addPlugin(new RequestIdHeaderPlugin($this->request));
103
+
104
+        $server->addPlugin(new ZipFolderPlugin(
105
+            $tree,
106
+            $this->logger,
107
+            $this->eventDispatcher,
108
+        ));
109
+
110
+        // Some WebDAV clients do require Class 2 WebDAV support (locking), since
111
+        // we do not provide locking we emulate it using a fake locking plugin.
112
+        if ($this->request->isUserAgent([
113
+            '/WebDAVFS/',
114
+            '/OneNote/',
115
+            '/Microsoft-WebDAV-MiniRedir/',
116
+        ])) {
117
+            $server->addPlugin(new FakeLockerPlugin());
118
+        }
119
+
120
+        if (BrowserErrorPagePlugin::isBrowserRequest($this->request)) {
121
+            $server->addPlugin(new BrowserErrorPagePlugin());
122
+        }
123
+
124
+        // wait with registering these until auth is handled and the filesystem is setup
125
+        $server->on('beforeMethod:*', function () use ($server, $tree,
126
+            $viewCallBack, $isPublicShare, $rootCollection, $debugEnabled): void {
127
+            // ensure the skeleton is copied
128
+            $userFolder = \OC::$server->getUserFolder();
129
+
130
+            /** @var View $view */
131
+            $view = $viewCallBack($server);
132
+            if ($userFolder instanceof Folder && $userFolder->getPath() === $view->getRoot()) {
133
+                $rootInfo = $userFolder;
134
+            } else {
135
+                $rootInfo = $view->getFileInfo('');
136
+            }
137
+
138
+            // Create Nextcloud Dir
139
+            if ($rootInfo->getType() === 'dir') {
140
+                $root = new Directory($view, $rootInfo, $tree);
141
+            } else {
142
+                $root = new File($view, $rootInfo);
143
+            }
144
+
145
+            if ($isPublicShare) {
146
+                $userPrincipalBackend = new Principal(
147
+                    \OCP\Server::get(IUserManager::class),
148
+                    \OCP\Server::get(IGroupManager::class),
149
+                    \OCP\Server::get(IAccountManager::class),
150
+                    \OCP\Server::get(\OCP\Share\IManager::class),
151
+                    \OCP\Server::get(IUserSession::class),
152
+                    \OCP\Server::get(IAppManager::class),
153
+                    \OCP\Server::get(ProxyMapper::class),
154
+                    \OCP\Server::get(KnownUserService::class),
155
+                    \OCP\Server::get(IConfig::class),
156
+                    \OC::$server->getL10NFactory(),
157
+                );
158
+
159
+                // Mount the share collection at /public.php/dav/shares/<share token>
160
+                $rootCollection->addChild(new RootCollection(
161
+                    $root,
162
+                    $userPrincipalBackend,
163
+                    'principals/shares',
164
+                ));
165
+
166
+                // Mount the upload collection at /public.php/dav/uploads/<share token>
167
+                $rootCollection->addChild(new \OCA\DAV\Upload\RootCollection(
168
+                    $userPrincipalBackend,
169
+                    'principals/shares',
170
+                    \OCP\Server::get(CleanupService::class),
171
+                    \OCP\Server::get(IRootFolder::class),
172
+                    \OCP\Server::get(IUserSession::class),
173
+                    \OCP\Server::get(\OCP\Share\IManager::class),
174
+                ));
175
+            } else {
176
+                /** @var ObjectTree $tree */
177
+                $tree->init($root, $view, $this->mountManager);
178
+            }
179
+
180
+            $server->addPlugin(
181
+                new FilesPlugin(
182
+                    $tree,
183
+                    $this->config,
184
+                    $this->request,
185
+                    $this->previewManager,
186
+                    $this->userSession,
187
+                    \OCP\Server::get(IFilenameValidator::class),
188
+                    \OCP\Server::get(IAccountManager::class),
189
+                    false,
190
+                    !$debugEnabled
191
+                )
192
+            );
193
+            $server->addPlugin(new QuotaPlugin($view));
194
+            $server->addPlugin(new ChecksumUpdatePlugin());
195
+
196
+            // Allow view-only plugin for webdav requests
197
+            $server->addPlugin(new ViewOnlyPlugin(
198
+                $userFolder,
199
+            ));
200
+
201
+            if ($this->userSession->isLoggedIn()) {
202
+                $server->addPlugin(new TagsPlugin($tree, $this->tagManager, $this->eventDispatcher, $this->userSession));
203
+                $server->addPlugin(new SharesPlugin(
204
+                    $tree,
205
+                    $this->userSession,
206
+                    $userFolder,
207
+                    \OCP\Server::get(\OCP\Share\IManager::class)
208
+                ));
209
+                $server->addPlugin(new CommentPropertiesPlugin(\OCP\Server::get(ICommentsManager::class), $this->userSession));
210
+                $server->addPlugin(new FilesReportPlugin(
211
+                    $tree,
212
+                    $view,
213
+                    \OCP\Server::get(ISystemTagManager::class),
214
+                    \OCP\Server::get(ISystemTagObjectMapper::class),
215
+                    \OCP\Server::get(ITagManager::class),
216
+                    $this->userSession,
217
+                    \OCP\Server::get(IGroupManager::class),
218
+                    $userFolder,
219
+                    \OCP\Server::get(IAppManager::class)
220
+                ));
221
+                // custom properties plugin must be the last one
222
+                $server->addPlugin(
223
+                    new \Sabre\DAV\PropertyStorage\Plugin(
224
+                        new CustomPropertiesBackend(
225
+                            $server,
226
+                            $tree,
227
+                            $this->databaseConnection,
228
+                            $this->userSession->getUser(),
229
+                            \OCP\Server::get(DefaultCalendarValidator::class),
230
+                        )
231
+                    )
232
+                );
233
+            }
234
+            $server->addPlugin(new CopyEtagHeaderPlugin());
235
+
236
+            // Load dav plugins from apps
237
+            $event = new SabrePluginEvent($server);
238
+            $this->eventDispatcher->dispatchTyped($event);
239
+            $pluginManager = new PluginManager(
240
+                \OC::$server,
241
+                \OCP\Server::get(IAppManager::class)
242
+            );
243
+            foreach ($pluginManager->getAppPlugins() as $appPlugin) {
244
+                $server->addPlugin($appPlugin);
245
+            }
246
+        }, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request
247
+        return $server;
248
+    }
249 249
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/PropFindMonitorPlugin.php 1 patch
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -19,60 +19,60 @@
 block discarded – undo
19 19
  */
20 20
 class PropFindMonitorPlugin extends ServerPlugin {
21 21
 
22
-	/**
23
-	 * A Plugin can scan up to this amount of nodes without an error being
24
-	 * reported.
25
-	 */
26
-	public const THRESHOLD_NODES = 50;
22
+    /**
23
+     * A Plugin can scan up to this amount of nodes without an error being
24
+     * reported.
25
+     */
26
+    public const THRESHOLD_NODES = 50;
27 27
 
28
-	/**
29
-	 * A plugin can use up to this amount of queries per node.
30
-	 */
31
-	public const THRESHOLD_QUERY_FACTOR = 1;
28
+    /**
29
+     * A plugin can use up to this amount of queries per node.
30
+     */
31
+    public const THRESHOLD_QUERY_FACTOR = 1;
32 32
 
33
-	private SabreServer $server;
33
+    private SabreServer $server;
34 34
 
35
-	public function initialize(SabreServer $server): void {
36
-		$this->server = $server;
37
-		$this->server->on('afterResponse', [$this, 'afterResponse']);
38
-	}
35
+    public function initialize(SabreServer $server): void {
36
+        $this->server = $server;
37
+        $this->server->on('afterResponse', [$this, 'afterResponse']);
38
+    }
39 39
 
40
-	public function afterResponse(
41
-		RequestInterface $request,
42
-		ResponseInterface $response): void {
43
-		if (!$this->server instanceof Server) {
44
-			return;
45
-		}
40
+    public function afterResponse(
41
+        RequestInterface $request,
42
+        ResponseInterface $response): void {
43
+        if (!$this->server instanceof Server) {
44
+            return;
45
+        }
46 46
 
47
-		$pluginQueries = $this->server->getPluginQueries();
48
-		if (empty($pluginQueries)) {
49
-			return;
50
-		}
51
-		$maxDepth = max(0, ...array_keys($pluginQueries));
52
-		// entries at the top are usually not interesting
53
-		unset($pluginQueries[$maxDepth]);
47
+        $pluginQueries = $this->server->getPluginQueries();
48
+        if (empty($pluginQueries)) {
49
+            return;
50
+        }
51
+        $maxDepth = max(0, ...array_keys($pluginQueries));
52
+        // entries at the top are usually not interesting
53
+        unset($pluginQueries[$maxDepth]);
54 54
 
55
-		$logger = $this->server->getLogger();
56
-		foreach ($pluginQueries as $depth => $propFinds) {
57
-			foreach ($propFinds as $pluginName => $propFind) {
58
-				[
59
-					'queries' => $queries,
60
-					'nodes' => $nodes
61
-				] = $propFind;
62
-				if ($queries === 0 || $nodes > $queries || $nodes < self::THRESHOLD_NODES
63
-					|| $queries < $nodes * self::THRESHOLD_QUERY_FACTOR) {
64
-					continue;
65
-				}
66
-				$logger->error(
67
-					'{name} scanned {scans} nodes with {count} queries in depth {depth}/{maxDepth}. This is bad for performance, please report to the plugin developer!', [
68
-						'name' => $pluginName,
69
-						'scans' => $nodes,
70
-						'count' => $queries,
71
-						'depth' => $depth,
72
-						'maxDepth' => $maxDepth,
73
-					]
74
-				);
75
-			}
76
-		}
77
-	}
55
+        $logger = $this->server->getLogger();
56
+        foreach ($pluginQueries as $depth => $propFinds) {
57
+            foreach ($propFinds as $pluginName => $propFind) {
58
+                [
59
+                    'queries' => $queries,
60
+                    'nodes' => $nodes
61
+                ] = $propFind;
62
+                if ($queries === 0 || $nodes > $queries || $nodes < self::THRESHOLD_NODES
63
+                    || $queries < $nodes * self::THRESHOLD_QUERY_FACTOR) {
64
+                    continue;
65
+                }
66
+                $logger->error(
67
+                    '{name} scanned {scans} nodes with {count} queries in depth {depth}/{maxDepth}. This is bad for performance, please report to the plugin developer!', [
68
+                        'name' => $pluginName,
69
+                        'scans' => $nodes,
70
+                        'count' => $queries,
71
+                        'depth' => $depth,
72
+                        'maxDepth' => $maxDepth,
73
+                    ]
74
+                );
75
+            }
76
+        }
77
+    }
78 78
 }
Please login to merge, or discard this patch.
apps/dav/lib/Server.php 1 patch
Indentation   +330 added lines, -330 removed lines patch added patch discarded remove patch
@@ -102,335 +102,335 @@
 block discarded – undo
102 102
 use SearchDAV\DAV\SearchPlugin;
103 103
 
104 104
 class Server {
105
-	public Connector\Sabre\Server $server;
106
-	private IProfiler $profiler;
107
-
108
-	public function __construct(
109
-		private IRequest $request,
110
-		private string $baseUri,
111
-	) {
112
-		$debugEnabled = \OCP\Server::get(IConfig::class)->getSystemValue('debug', false);
113
-		$this->profiler = \OCP\Server::get(IProfiler::class);
114
-		if ($this->profiler->isEnabled()) {
115
-			/** @var IEventLogger $eventLogger */
116
-			$eventLogger = \OCP\Server::get(IEventLogger::class);
117
-			$eventLogger->start('runtime', 'DAV Runtime');
118
-		}
119
-
120
-		$logger = \OCP\Server::get(LoggerInterface::class);
121
-		$eventDispatcher = \OCP\Server::get(IEventDispatcher::class);
122
-
123
-		$root = new RootCollection();
124
-		$this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
125
-		$this->server->setLogger($logger);
126
-
127
-		// Add maintenance plugin
128
-		$this->server->addPlugin(new MaintenancePlugin(\OCP\Server::get(IConfig::class), \OC::$server->getL10N('dav')));
129
-
130
-		$this->server->addPlugin(new AppleQuirksPlugin());
131
-
132
-		// Backends
133
-		$authBackend = new Auth(
134
-			\OCP\Server::get(ISession::class),
135
-			\OCP\Server::get(IUserSession::class),
136
-			\OCP\Server::get(IRequest::class),
137
-			\OCP\Server::get(\OC\Authentication\TwoFactorAuth\Manager::class),
138
-			\OCP\Server::get(IThrottler::class)
139
-		);
140
-
141
-		// Set URL explicitly due to reverse-proxy situations
142
-		$this->server->httpRequest->setUrl($this->request->getRequestUri());
143
-		$this->server->setBaseUri($this->baseUri);
144
-
145
-		$this->server->addPlugin(new ProfilerPlugin($this->request));
146
-		$this->server->addPlugin(new BlockLegacyClientPlugin(
147
-			\OCP\Server::get(IConfig::class),
148
-			\OCP\Server::get(ThemingDefaults::class),
149
-		));
150
-		$this->server->addPlugin(new AnonymousOptionsPlugin());
151
-		$authPlugin = new Plugin();
152
-		$authPlugin->addBackend(new PublicAuth());
153
-		$this->server->addPlugin($authPlugin);
154
-
155
-		// allow setup of additional auth backends
156
-		$event = new SabrePluginEvent($this->server);
157
-		$eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
158
-
159
-		$newAuthEvent = new SabrePluginAuthInitEvent($this->server);
160
-		$eventDispatcher->dispatchTyped($newAuthEvent);
161
-
162
-		$bearerAuthBackend = new BearerAuth(
163
-			\OCP\Server::get(IUserSession::class),
164
-			\OCP\Server::get(ISession::class),
165
-			\OCP\Server::get(IRequest::class),
166
-			\OCP\Server::get(IConfig::class),
167
-		);
168
-		$authPlugin->addBackend($bearerAuthBackend);
169
-		// because we are throwing exceptions this plugin has to be the last one
170
-		$authPlugin->addBackend($authBackend);
171
-
172
-		// debugging
173
-		if ($debugEnabled) {
174
-			$this->server->debugEnabled = true;
175
-			$this->server->addPlugin(new PropFindMonitorPlugin());
176
-			$this->server->addPlugin(new \Sabre\DAV\Browser\Plugin());
177
-		} else {
178
-			$this->server->addPlugin(new DummyGetResponsePlugin());
179
-		}
180
-
181
-		$this->server->addPlugin(new ExceptionLoggerPlugin('webdav', $logger));
182
-		$this->server->addPlugin(new LockPlugin());
183
-		$this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
184
-
185
-		// acl
186
-		$acl = new DavAclPlugin();
187
-		$acl->principalCollectionSet = [
188
-			'principals/users',
189
-			'principals/groups',
190
-			'principals/calendar-resources',
191
-			'principals/calendar-rooms',
192
-		];
193
-		$this->server->addPlugin($acl);
194
-
195
-		// calendar plugins
196
-		if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) {
197
-			$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OCP\Server::get(IRequest::class), \OCP\Server::get(IConfig::class)));
198
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
199
-			$this->server->addPlugin(new ICSExportPlugin(\OCP\Server::get(IConfig::class), $logger));
200
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OCP\Server::get(IConfig::class), \OCP\Server::get(LoggerInterface::class), \OCP\Server::get(DefaultCalendarValidator::class)));
201
-
202
-			$this->server->addPlugin(\OCP\Server::get(\OCA\DAV\CalDAV\Trashbin\Plugin::class));
203
-			$this->server->addPlugin(new \OCA\DAV\CalDAV\WebcalCaching\Plugin($this->request));
204
-			if (\OCP\Server::get(IConfig::class)->getAppValue('dav', 'allow_calendar_link_subscriptions', 'yes') === 'yes') {
205
-				$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
206
-			}
207
-
208
-			$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
209
-			$this->server->addPlugin(new PublishPlugin(
210
-				\OCP\Server::get(IConfig::class),
211
-				\OCP\Server::get(IURLGenerator::class)
212
-			));
213
-
214
-			$this->server->addPlugin(\OCP\Server::get(RateLimitingPlugin::class));
215
-			$this->server->addPlugin(\OCP\Server::get(CalDavValidatePlugin::class));
216
-		}
217
-
218
-		// addressbook plugins
219
-		if ($this->requestIsForSubtree(['addressbooks', 'principals'])) {
220
-			$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OCP\Server::get(IRequest::class), \OCP\Server::get(IConfig::class)));
221
-			$this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
222
-			$this->server->addPlugin(new VCFExportPlugin());
223
-			$this->server->addPlugin(new MultiGetExportPlugin());
224
-			$this->server->addPlugin(new HasPhotoPlugin());
225
-			$this->server->addPlugin(new ImageExportPlugin(\OCP\Server::get(PhotoCache::class)));
226
-
227
-			$this->server->addPlugin(\OCP\Server::get(CardDavRateLimitingPlugin::class));
228
-			$this->server->addPlugin(\OCP\Server::get(CardDavValidatePlugin::class));
229
-		}
230
-
231
-		// system tags plugins
232
-		$this->server->addPlugin(\OCP\Server::get(SystemTagPlugin::class));
233
-
234
-		// comments plugin
235
-		$this->server->addPlugin(new CommentsPlugin(
236
-			\OCP\Server::get(ICommentsManager::class),
237
-			\OCP\Server::get(IUserSession::class)
238
-		));
239
-
240
-		$this->server->addPlugin(new CopyEtagHeaderPlugin());
241
-		$this->server->addPlugin(new RequestIdHeaderPlugin(\OCP\Server::get(IRequest::class)));
242
-		$this->server->addPlugin(new UploadAutoMkcolPlugin());
243
-		$this->server->addPlugin(new ChunkingV2Plugin(\OCP\Server::get(ICacheFactory::class)));
244
-		$this->server->addPlugin(new ChunkingPlugin());
245
-		$this->server->addPlugin(new ZipFolderPlugin(
246
-			$this->server->tree,
247
-			$logger,
248
-			$eventDispatcher,
249
-		));
250
-		$this->server->addPlugin(\OCP\Server::get(PaginatePlugin::class));
251
-
252
-		// allow setup of additional plugins
253
-		$eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);
254
-		$typedEvent = new SabrePluginAddEvent($this->server);
255
-		$eventDispatcher->dispatchTyped($typedEvent);
256
-
257
-		// Some WebDAV clients do require Class 2 WebDAV support (locking), since
258
-		// we do not provide locking we emulate it using a fake locking plugin.
259
-		if ($this->request->isUserAgent([
260
-			'/WebDAVFS/',
261
-			'/OneNote/',
262
-			'/^Microsoft-WebDAV/',// Microsoft-WebDAV-MiniRedir/6.1.7601
263
-		])) {
264
-			$this->server->addPlugin(new FakeLockerPlugin());
265
-		}
266
-
267
-		if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
268
-			$this->server->addPlugin(new BrowserErrorPagePlugin());
269
-		}
270
-
271
-		$lazySearchBackend = new LazySearchBackend();
272
-		$this->server->addPlugin(new SearchPlugin($lazySearchBackend));
273
-
274
-		// wait with registering these until auth is handled and the filesystem is setup
275
-		$this->server->on('beforeMethod:*', function () use ($root, $lazySearchBackend, $logger): void {
276
-			// Allow view-only plugin for webdav requests
277
-			$this->server->addPlugin(new ViewOnlyPlugin(
278
-				\OC::$server->getUserFolder(),
279
-			));
280
-
281
-			// custom properties plugin must be the last one
282
-			$userSession = \OCP\Server::get(IUserSession::class);
283
-			$user = $userSession->getUser();
284
-			if ($user !== null) {
285
-				$view = Filesystem::getView();
286
-				$config = \OCP\Server::get(IConfig::class);
287
-				$this->server->addPlugin(
288
-					new FilesPlugin(
289
-						$this->server->tree,
290
-						$config,
291
-						$this->request,
292
-						\OCP\Server::get(IPreview::class),
293
-						\OCP\Server::get(IUserSession::class),
294
-						\OCP\Server::get(IFilenameValidator::class),
295
-						\OCP\Server::get(IAccountManager::class),
296
-						false,
297
-						$config->getSystemValueBool('debug', false) === false,
298
-					)
299
-				);
300
-				$this->server->addPlugin(new ChecksumUpdatePlugin());
301
-
302
-				$this->server->addPlugin(
303
-					new \Sabre\DAV\PropertyStorage\Plugin(
304
-						new CustomPropertiesBackend(
305
-							$this->server,
306
-							$this->server->tree,
307
-							\OCP\Server::get(IDBConnection::class),
308
-							\OCP\Server::get(IUserSession::class)->getUser(),
309
-							\OCP\Server::get(DefaultCalendarValidator::class),
310
-						)
311
-					)
312
-				);
313
-				if ($view !== null) {
314
-					$this->server->addPlugin(
315
-						new QuotaPlugin($view));
316
-				}
317
-				$this->server->addPlugin(
318
-					new TagsPlugin(
319
-						$this->server->tree, \OCP\Server::get(ITagManager::class), \OCP\Server::get(IEventDispatcher::class), \OCP\Server::get(IUserSession::class)
320
-					)
321
-				);
322
-
323
-				// TODO: switch to LazyUserFolder
324
-				$userFolder = \OC::$server->getUserFolder();
325
-				$shareManager = \OCP\Server::get(\OCP\Share\IManager::class);
326
-				$this->server->addPlugin(new SharesPlugin(
327
-					$this->server->tree,
328
-					$userSession,
329
-					$userFolder,
330
-					$shareManager,
331
-				));
332
-				$this->server->addPlugin(new CommentPropertiesPlugin(
333
-					\OCP\Server::get(ICommentsManager::class),
334
-					$userSession
335
-				));
336
-				if (\OCP\Server::get(IConfig::class)->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') {
337
-					$this->server->addPlugin(new IMipPlugin(
338
-						\OCP\Server::get(IAppConfig::class),
339
-						\OCP\Server::get(IMailer::class),
340
-						\OCP\Server::get(LoggerInterface::class),
341
-						\OCP\Server::get(ITimeFactory::class),
342
-						\OCP\Server::get(Defaults::class),
343
-						$userSession,
344
-						\OCP\Server::get(IMipService::class),
345
-						\OCP\Server::get(EventComparisonService::class),
346
-						\OCP\Server::get(\OCP\Mail\Provider\IManager::class)
347
-					));
348
-				}
349
-				$this->server->addPlugin(new \OCA\DAV\CalDAV\Search\SearchPlugin());
350
-				if ($view !== null) {
351
-					$this->server->addPlugin(new FilesReportPlugin(
352
-						$this->server->tree,
353
-						$view,
354
-						\OCP\Server::get(ISystemTagManager::class),
355
-						\OCP\Server::get(ISystemTagObjectMapper::class),
356
-						\OCP\Server::get(ITagManager::class),
357
-						$userSession,
358
-						\OCP\Server::get(IGroupManager::class),
359
-						$userFolder,
360
-						\OCP\Server::get(IAppManager::class)
361
-					));
362
-					$lazySearchBackend->setBackend(new FileSearchBackend(
363
-						$this->server,
364
-						$this->server->tree,
365
-						$user,
366
-						\OCP\Server::get(IRootFolder::class),
367
-						$shareManager,
368
-						$view,
369
-						\OCP\Server::get(IFilesMetadataManager::class)
370
-					));
371
-					$this->server->addPlugin(
372
-						new BulkUploadPlugin(
373
-							$userFolder,
374
-							$logger
375
-						)
376
-					);
377
-				}
378
-				$this->server->addPlugin(new EnablePlugin(
379
-					\OCP\Server::get(IConfig::class),
380
-					\OCP\Server::get(BirthdayService::class),
381
-					$user
382
-				));
383
-				$this->server->addPlugin(new AppleProvisioningPlugin(
384
-					\OCP\Server::get(IUserSession::class),
385
-					\OCP\Server::get(IURLGenerator::class),
386
-					\OCP\Server::get(ThemingDefaults::class),
387
-					\OCP\Server::get(IRequest::class),
388
-					\OC::$server->getL10N('dav'),
389
-					function () {
390
-						return UUIDUtil::getUUID();
391
-					}
392
-				));
393
-			}
394
-
395
-			// register plugins from apps
396
-			$pluginManager = new PluginManager(
397
-				\OC::$server,
398
-				\OCP\Server::get(IAppManager::class)
399
-			);
400
-			foreach ($pluginManager->getAppPlugins() as $appPlugin) {
401
-				$this->server->addPlugin($appPlugin);
402
-			}
403
-			foreach ($pluginManager->getAppCollections() as $appCollection) {
404
-				$root->addChild($appCollection);
405
-			}
406
-		});
407
-
408
-		$this->server->addPlugin(
409
-			new PropfindCompressionPlugin()
410
-		);
411
-	}
412
-
413
-	public function exec() {
414
-		/** @var IEventLogger $eventLogger */
415
-		$eventLogger = \OCP\Server::get(IEventLogger::class);
416
-		$eventLogger->start('dav_server_exec', '');
417
-		$this->server->start();
418
-		$eventLogger->end('dav_server_exec');
419
-		if ($this->profiler->isEnabled()) {
420
-			$eventLogger->end('runtime');
421
-			$profile = $this->profiler->collect(\OCP\Server::get(IRequest::class), new Response());
422
-			$this->profiler->saveProfile($profile);
423
-		}
424
-	}
425
-
426
-	private function requestIsForSubtree(array $subTrees): bool {
427
-		foreach ($subTrees as $subTree) {
428
-			$subTree = trim($subTree, ' /');
429
-			if (str_starts_with($this->server->getRequestUri(), $subTree . '/')) {
430
-				return true;
431
-			}
432
-		}
433
-		return false;
434
-	}
105
+    public Connector\Sabre\Server $server;
106
+    private IProfiler $profiler;
107
+
108
+    public function __construct(
109
+        private IRequest $request,
110
+        private string $baseUri,
111
+    ) {
112
+        $debugEnabled = \OCP\Server::get(IConfig::class)->getSystemValue('debug', false);
113
+        $this->profiler = \OCP\Server::get(IProfiler::class);
114
+        if ($this->profiler->isEnabled()) {
115
+            /** @var IEventLogger $eventLogger */
116
+            $eventLogger = \OCP\Server::get(IEventLogger::class);
117
+            $eventLogger->start('runtime', 'DAV Runtime');
118
+        }
119
+
120
+        $logger = \OCP\Server::get(LoggerInterface::class);
121
+        $eventDispatcher = \OCP\Server::get(IEventDispatcher::class);
122
+
123
+        $root = new RootCollection();
124
+        $this->server = new \OCA\DAV\Connector\Sabre\Server(new CachingTree($root));
125
+        $this->server->setLogger($logger);
126
+
127
+        // Add maintenance plugin
128
+        $this->server->addPlugin(new MaintenancePlugin(\OCP\Server::get(IConfig::class), \OC::$server->getL10N('dav')));
129
+
130
+        $this->server->addPlugin(new AppleQuirksPlugin());
131
+
132
+        // Backends
133
+        $authBackend = new Auth(
134
+            \OCP\Server::get(ISession::class),
135
+            \OCP\Server::get(IUserSession::class),
136
+            \OCP\Server::get(IRequest::class),
137
+            \OCP\Server::get(\OC\Authentication\TwoFactorAuth\Manager::class),
138
+            \OCP\Server::get(IThrottler::class)
139
+        );
140
+
141
+        // Set URL explicitly due to reverse-proxy situations
142
+        $this->server->httpRequest->setUrl($this->request->getRequestUri());
143
+        $this->server->setBaseUri($this->baseUri);
144
+
145
+        $this->server->addPlugin(new ProfilerPlugin($this->request));
146
+        $this->server->addPlugin(new BlockLegacyClientPlugin(
147
+            \OCP\Server::get(IConfig::class),
148
+            \OCP\Server::get(ThemingDefaults::class),
149
+        ));
150
+        $this->server->addPlugin(new AnonymousOptionsPlugin());
151
+        $authPlugin = new Plugin();
152
+        $authPlugin->addBackend(new PublicAuth());
153
+        $this->server->addPlugin($authPlugin);
154
+
155
+        // allow setup of additional auth backends
156
+        $event = new SabrePluginEvent($this->server);
157
+        $eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
158
+
159
+        $newAuthEvent = new SabrePluginAuthInitEvent($this->server);
160
+        $eventDispatcher->dispatchTyped($newAuthEvent);
161
+
162
+        $bearerAuthBackend = new BearerAuth(
163
+            \OCP\Server::get(IUserSession::class),
164
+            \OCP\Server::get(ISession::class),
165
+            \OCP\Server::get(IRequest::class),
166
+            \OCP\Server::get(IConfig::class),
167
+        );
168
+        $authPlugin->addBackend($bearerAuthBackend);
169
+        // because we are throwing exceptions this plugin has to be the last one
170
+        $authPlugin->addBackend($authBackend);
171
+
172
+        // debugging
173
+        if ($debugEnabled) {
174
+            $this->server->debugEnabled = true;
175
+            $this->server->addPlugin(new PropFindMonitorPlugin());
176
+            $this->server->addPlugin(new \Sabre\DAV\Browser\Plugin());
177
+        } else {
178
+            $this->server->addPlugin(new DummyGetResponsePlugin());
179
+        }
180
+
181
+        $this->server->addPlugin(new ExceptionLoggerPlugin('webdav', $logger));
182
+        $this->server->addPlugin(new LockPlugin());
183
+        $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
184
+
185
+        // acl
186
+        $acl = new DavAclPlugin();
187
+        $acl->principalCollectionSet = [
188
+            'principals/users',
189
+            'principals/groups',
190
+            'principals/calendar-resources',
191
+            'principals/calendar-rooms',
192
+        ];
193
+        $this->server->addPlugin($acl);
194
+
195
+        // calendar plugins
196
+        if ($this->requestIsForSubtree(['calendars', 'public-calendars', 'system-calendars', 'principals'])) {
197
+            $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OCP\Server::get(IRequest::class), \OCP\Server::get(IConfig::class)));
198
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
199
+            $this->server->addPlugin(new ICSExportPlugin(\OCP\Server::get(IConfig::class), $logger));
200
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\Schedule\Plugin(\OCP\Server::get(IConfig::class), \OCP\Server::get(LoggerInterface::class), \OCP\Server::get(DefaultCalendarValidator::class)));
201
+
202
+            $this->server->addPlugin(\OCP\Server::get(\OCA\DAV\CalDAV\Trashbin\Plugin::class));
203
+            $this->server->addPlugin(new \OCA\DAV\CalDAV\WebcalCaching\Plugin($this->request));
204
+            if (\OCP\Server::get(IConfig::class)->getAppValue('dav', 'allow_calendar_link_subscriptions', 'yes') === 'yes') {
205
+                $this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
206
+            }
207
+
208
+            $this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
209
+            $this->server->addPlugin(new PublishPlugin(
210
+                \OCP\Server::get(IConfig::class),
211
+                \OCP\Server::get(IURLGenerator::class)
212
+            ));
213
+
214
+            $this->server->addPlugin(\OCP\Server::get(RateLimitingPlugin::class));
215
+            $this->server->addPlugin(\OCP\Server::get(CalDavValidatePlugin::class));
216
+        }
217
+
218
+        // addressbook plugins
219
+        if ($this->requestIsForSubtree(['addressbooks', 'principals'])) {
220
+            $this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OCP\Server::get(IRequest::class), \OCP\Server::get(IConfig::class)));
221
+            $this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
222
+            $this->server->addPlugin(new VCFExportPlugin());
223
+            $this->server->addPlugin(new MultiGetExportPlugin());
224
+            $this->server->addPlugin(new HasPhotoPlugin());
225
+            $this->server->addPlugin(new ImageExportPlugin(\OCP\Server::get(PhotoCache::class)));
226
+
227
+            $this->server->addPlugin(\OCP\Server::get(CardDavRateLimitingPlugin::class));
228
+            $this->server->addPlugin(\OCP\Server::get(CardDavValidatePlugin::class));
229
+        }
230
+
231
+        // system tags plugins
232
+        $this->server->addPlugin(\OCP\Server::get(SystemTagPlugin::class));
233
+
234
+        // comments plugin
235
+        $this->server->addPlugin(new CommentsPlugin(
236
+            \OCP\Server::get(ICommentsManager::class),
237
+            \OCP\Server::get(IUserSession::class)
238
+        ));
239
+
240
+        $this->server->addPlugin(new CopyEtagHeaderPlugin());
241
+        $this->server->addPlugin(new RequestIdHeaderPlugin(\OCP\Server::get(IRequest::class)));
242
+        $this->server->addPlugin(new UploadAutoMkcolPlugin());
243
+        $this->server->addPlugin(new ChunkingV2Plugin(\OCP\Server::get(ICacheFactory::class)));
244
+        $this->server->addPlugin(new ChunkingPlugin());
245
+        $this->server->addPlugin(new ZipFolderPlugin(
246
+            $this->server->tree,
247
+            $logger,
248
+            $eventDispatcher,
249
+        ));
250
+        $this->server->addPlugin(\OCP\Server::get(PaginatePlugin::class));
251
+
252
+        // allow setup of additional plugins
253
+        $eventDispatcher->dispatch('OCA\DAV\Connector\Sabre::addPlugin', $event);
254
+        $typedEvent = new SabrePluginAddEvent($this->server);
255
+        $eventDispatcher->dispatchTyped($typedEvent);
256
+
257
+        // Some WebDAV clients do require Class 2 WebDAV support (locking), since
258
+        // we do not provide locking we emulate it using a fake locking plugin.
259
+        if ($this->request->isUserAgent([
260
+            '/WebDAVFS/',
261
+            '/OneNote/',
262
+            '/^Microsoft-WebDAV/',// Microsoft-WebDAV-MiniRedir/6.1.7601
263
+        ])) {
264
+            $this->server->addPlugin(new FakeLockerPlugin());
265
+        }
266
+
267
+        if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
268
+            $this->server->addPlugin(new BrowserErrorPagePlugin());
269
+        }
270
+
271
+        $lazySearchBackend = new LazySearchBackend();
272
+        $this->server->addPlugin(new SearchPlugin($lazySearchBackend));
273
+
274
+        // wait with registering these until auth is handled and the filesystem is setup
275
+        $this->server->on('beforeMethod:*', function () use ($root, $lazySearchBackend, $logger): void {
276
+            // Allow view-only plugin for webdav requests
277
+            $this->server->addPlugin(new ViewOnlyPlugin(
278
+                \OC::$server->getUserFolder(),
279
+            ));
280
+
281
+            // custom properties plugin must be the last one
282
+            $userSession = \OCP\Server::get(IUserSession::class);
283
+            $user = $userSession->getUser();
284
+            if ($user !== null) {
285
+                $view = Filesystem::getView();
286
+                $config = \OCP\Server::get(IConfig::class);
287
+                $this->server->addPlugin(
288
+                    new FilesPlugin(
289
+                        $this->server->tree,
290
+                        $config,
291
+                        $this->request,
292
+                        \OCP\Server::get(IPreview::class),
293
+                        \OCP\Server::get(IUserSession::class),
294
+                        \OCP\Server::get(IFilenameValidator::class),
295
+                        \OCP\Server::get(IAccountManager::class),
296
+                        false,
297
+                        $config->getSystemValueBool('debug', false) === false,
298
+                    )
299
+                );
300
+                $this->server->addPlugin(new ChecksumUpdatePlugin());
301
+
302
+                $this->server->addPlugin(
303
+                    new \Sabre\DAV\PropertyStorage\Plugin(
304
+                        new CustomPropertiesBackend(
305
+                            $this->server,
306
+                            $this->server->tree,
307
+                            \OCP\Server::get(IDBConnection::class),
308
+                            \OCP\Server::get(IUserSession::class)->getUser(),
309
+                            \OCP\Server::get(DefaultCalendarValidator::class),
310
+                        )
311
+                    )
312
+                );
313
+                if ($view !== null) {
314
+                    $this->server->addPlugin(
315
+                        new QuotaPlugin($view));
316
+                }
317
+                $this->server->addPlugin(
318
+                    new TagsPlugin(
319
+                        $this->server->tree, \OCP\Server::get(ITagManager::class), \OCP\Server::get(IEventDispatcher::class), \OCP\Server::get(IUserSession::class)
320
+                    )
321
+                );
322
+
323
+                // TODO: switch to LazyUserFolder
324
+                $userFolder = \OC::$server->getUserFolder();
325
+                $shareManager = \OCP\Server::get(\OCP\Share\IManager::class);
326
+                $this->server->addPlugin(new SharesPlugin(
327
+                    $this->server->tree,
328
+                    $userSession,
329
+                    $userFolder,
330
+                    $shareManager,
331
+                ));
332
+                $this->server->addPlugin(new CommentPropertiesPlugin(
333
+                    \OCP\Server::get(ICommentsManager::class),
334
+                    $userSession
335
+                ));
336
+                if (\OCP\Server::get(IConfig::class)->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') {
337
+                    $this->server->addPlugin(new IMipPlugin(
338
+                        \OCP\Server::get(IAppConfig::class),
339
+                        \OCP\Server::get(IMailer::class),
340
+                        \OCP\Server::get(LoggerInterface::class),
341
+                        \OCP\Server::get(ITimeFactory::class),
342
+                        \OCP\Server::get(Defaults::class),
343
+                        $userSession,
344
+                        \OCP\Server::get(IMipService::class),
345
+                        \OCP\Server::get(EventComparisonService::class),
346
+                        \OCP\Server::get(\OCP\Mail\Provider\IManager::class)
347
+                    ));
348
+                }
349
+                $this->server->addPlugin(new \OCA\DAV\CalDAV\Search\SearchPlugin());
350
+                if ($view !== null) {
351
+                    $this->server->addPlugin(new FilesReportPlugin(
352
+                        $this->server->tree,
353
+                        $view,
354
+                        \OCP\Server::get(ISystemTagManager::class),
355
+                        \OCP\Server::get(ISystemTagObjectMapper::class),
356
+                        \OCP\Server::get(ITagManager::class),
357
+                        $userSession,
358
+                        \OCP\Server::get(IGroupManager::class),
359
+                        $userFolder,
360
+                        \OCP\Server::get(IAppManager::class)
361
+                    ));
362
+                    $lazySearchBackend->setBackend(new FileSearchBackend(
363
+                        $this->server,
364
+                        $this->server->tree,
365
+                        $user,
366
+                        \OCP\Server::get(IRootFolder::class),
367
+                        $shareManager,
368
+                        $view,
369
+                        \OCP\Server::get(IFilesMetadataManager::class)
370
+                    ));
371
+                    $this->server->addPlugin(
372
+                        new BulkUploadPlugin(
373
+                            $userFolder,
374
+                            $logger
375
+                        )
376
+                    );
377
+                }
378
+                $this->server->addPlugin(new EnablePlugin(
379
+                    \OCP\Server::get(IConfig::class),
380
+                    \OCP\Server::get(BirthdayService::class),
381
+                    $user
382
+                ));
383
+                $this->server->addPlugin(new AppleProvisioningPlugin(
384
+                    \OCP\Server::get(IUserSession::class),
385
+                    \OCP\Server::get(IURLGenerator::class),
386
+                    \OCP\Server::get(ThemingDefaults::class),
387
+                    \OCP\Server::get(IRequest::class),
388
+                    \OC::$server->getL10N('dav'),
389
+                    function () {
390
+                        return UUIDUtil::getUUID();
391
+                    }
392
+                ));
393
+            }
394
+
395
+            // register plugins from apps
396
+            $pluginManager = new PluginManager(
397
+                \OC::$server,
398
+                \OCP\Server::get(IAppManager::class)
399
+            );
400
+            foreach ($pluginManager->getAppPlugins() as $appPlugin) {
401
+                $this->server->addPlugin($appPlugin);
402
+            }
403
+            foreach ($pluginManager->getAppCollections() as $appCollection) {
404
+                $root->addChild($appCollection);
405
+            }
406
+        });
407
+
408
+        $this->server->addPlugin(
409
+            new PropfindCompressionPlugin()
410
+        );
411
+    }
412
+
413
+    public function exec() {
414
+        /** @var IEventLogger $eventLogger */
415
+        $eventLogger = \OCP\Server::get(IEventLogger::class);
416
+        $eventLogger->start('dav_server_exec', '');
417
+        $this->server->start();
418
+        $eventLogger->end('dav_server_exec');
419
+        if ($this->profiler->isEnabled()) {
420
+            $eventLogger->end('runtime');
421
+            $profile = $this->profiler->collect(\OCP\Server::get(IRequest::class), new Response());
422
+            $this->profiler->saveProfile($profile);
423
+        }
424
+    }
425
+
426
+    private function requestIsForSubtree(array $subTrees): bool {
427
+        foreach ($subTrees as $subTree) {
428
+            $subTree = trim($subTree, ' /');
429
+            if (str_starts_with($this->server->getRequestUri(), $subTree . '/')) {
430
+                return true;
431
+            }
432
+        }
433
+        return false;
434
+    }
435 435
 
436 436
 }
Please login to merge, or discard this patch.
apps/dav/tests/unit/Connector/Sabre/PropFindMonitorPluginTest.php 1 patch
Indentation   +98 added lines, -98 removed lines patch added patch discarded remove patch
@@ -16,108 +16,108 @@
 block discarded – undo
16 16
 
17 17
 class PropFindMonitorPluginTest extends TestCase {
18 18
 
19
-	private PropFindMonitorPlugin $plugin;
20
-	private Server&MockObject $server;
21
-	private LoggerInterface&MockObject $logger;
22
-	private Request&MockObject $request;
23
-	private Response&MockObject $response;
19
+    private PropFindMonitorPlugin $plugin;
20
+    private Server&MockObject $server;
21
+    private LoggerInterface&MockObject $logger;
22
+    private Request&MockObject $request;
23
+    private Response&MockObject $response;
24 24
 
25
-	public static function dataTest(): array {
26
-		$minQueriesTrigger = PropFindMonitorPlugin::THRESHOLD_QUERY_FACTOR
27
-			* PropFindMonitorPlugin::THRESHOLD_NODES;
28
-		return [
29
-			'No queries logged' => [[], 0],
30
-			'Plugins with queries in less than threshold nodes should not be logged' => [
31
-				[
32
-					[
33
-						'PluginName' => ['queries' => 100, 'nodes'
34
-							=> PropFindMonitorPlugin::THRESHOLD_NODES - 1]
35
-					],
36
-					[],
37
-				],
38
-				0
39
-			],
40
-			'Plugins with query-to-node ratio less than threshold should not be logged' => [
41
-				[
42
-					[
43
-						'PluginName' => [
44
-							'queries' => $minQueriesTrigger - 1,
45
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES ],
46
-					],
47
-					[],
48
-				],
49
-				0
50
-			],
51
-			'Plugins with more nodes scanned than queries executed should not be logged' => [
52
-				[
53
-					[
54
-						'PluginName' => [
55
-							'queries' => $minQueriesTrigger,
56
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES * 2],
57
-					],
58
-					[],
59
-				],
60
-				0
61
-			],
62
-			'Plugins with queries only in highest depth level should not be logged' => [
63
-				[
64
-					[
65
-						'PluginName' => [
66
-							'queries' => $minQueriesTrigger,
67
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1
68
-						]
69
-					],
70
-					[
71
-						'PluginName' => [
72
-							'queries' => $minQueriesTrigger * 2,
73
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES
74
-						]
75
-					]
76
-				],
77
-				0
78
-			],
79
-			'Plugins with too many queries should be logged' => [
80
-				[
81
-					[
82
-						'FirstPlugin' => [
83
-							'queries' => $minQueriesTrigger,
84
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
85
-						],
86
-						'SecondPlugin' => [
87
-							'queries' => $minQueriesTrigger,
88
-							'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
89
-						]
90
-					],
91
-					[]
92
-				],
93
-				2
94
-			]
95
-		];
96
-	}
25
+    public static function dataTest(): array {
26
+        $minQueriesTrigger = PropFindMonitorPlugin::THRESHOLD_QUERY_FACTOR
27
+            * PropFindMonitorPlugin::THRESHOLD_NODES;
28
+        return [
29
+            'No queries logged' => [[], 0],
30
+            'Plugins with queries in less than threshold nodes should not be logged' => [
31
+                [
32
+                    [
33
+                        'PluginName' => ['queries' => 100, 'nodes'
34
+                            => PropFindMonitorPlugin::THRESHOLD_NODES - 1]
35
+                    ],
36
+                    [],
37
+                ],
38
+                0
39
+            ],
40
+            'Plugins with query-to-node ratio less than threshold should not be logged' => [
41
+                [
42
+                    [
43
+                        'PluginName' => [
44
+                            'queries' => $minQueriesTrigger - 1,
45
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES ],
46
+                    ],
47
+                    [],
48
+                ],
49
+                0
50
+            ],
51
+            'Plugins with more nodes scanned than queries executed should not be logged' => [
52
+                [
53
+                    [
54
+                        'PluginName' => [
55
+                            'queries' => $minQueriesTrigger,
56
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES * 2],
57
+                    ],
58
+                    [],
59
+                ],
60
+                0
61
+            ],
62
+            'Plugins with queries only in highest depth level should not be logged' => [
63
+                [
64
+                    [
65
+                        'PluginName' => [
66
+                            'queries' => $minQueriesTrigger,
67
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES - 1
68
+                        ]
69
+                    ],
70
+                    [
71
+                        'PluginName' => [
72
+                            'queries' => $minQueriesTrigger * 2,
73
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES
74
+                        ]
75
+                    ]
76
+                ],
77
+                0
78
+            ],
79
+            'Plugins with too many queries should be logged' => [
80
+                [
81
+                    [
82
+                        'FirstPlugin' => [
83
+                            'queries' => $minQueriesTrigger,
84
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
85
+                        ],
86
+                        'SecondPlugin' => [
87
+                            'queries' => $minQueriesTrigger,
88
+                            'nodes' => PropFindMonitorPlugin::THRESHOLD_NODES,
89
+                        ]
90
+                    ],
91
+                    []
92
+                ],
93
+                2
94
+            ]
95
+        ];
96
+    }
97 97
 
98
-	/**
99
-	 * @dataProvider dataTest
100
-	 */
101
-	public function test(array $queries, $expectedLogCalls): void {
102
-		$this->plugin->initialize($this->server);
103
-		$this->server->expects($this->once())->method('getPluginQueries')
104
-			->willReturn($queries);
98
+    /**
99
+     * @dataProvider dataTest
100
+     */
101
+    public function test(array $queries, $expectedLogCalls): void {
102
+        $this->plugin->initialize($this->server);
103
+        $this->server->expects($this->once())->method('getPluginQueries')
104
+            ->willReturn($queries);
105 105
 
106
-		$this->server->expects(empty($queries) ? $this->never() : $this->once())
107
-			->method('getLogger')
108
-			->willReturn($this->logger);
106
+        $this->server->expects(empty($queries) ? $this->never() : $this->once())
107
+            ->method('getLogger')
108
+            ->willReturn($this->logger);
109 109
 
110
-		$this->logger->expects($this->exactly($expectedLogCalls))->method('error');
111
-		$this->plugin->afterResponse($this->request, $this->response);
112
-	}
110
+        $this->logger->expects($this->exactly($expectedLogCalls))->method('error');
111
+        $this->plugin->afterResponse($this->request, $this->response);
112
+    }
113 113
 
114
-	protected function setUp(): void {
115
-		parent::setUp();
114
+    protected function setUp(): void {
115
+        parent::setUp();
116 116
 
117
-		$this->plugin = new PropFindMonitorPlugin();
118
-		$this->server = $this->createMock(Server::class);
119
-		$this->logger = $this->createMock(LoggerInterface::class);
120
-		$this->request = $this->createMock(Request::class);
121
-		$this->response = $this->createMock(Response::class);
122
-	}
117
+        $this->plugin = new PropFindMonitorPlugin();
118
+        $this->server = $this->createMock(Server::class);
119
+        $this->logger = $this->createMock(LoggerInterface::class);
120
+        $this->request = $this->createMock(Request::class);
121
+        $this->response = $this->createMock(Response::class);
122
+    }
123 123
 }
Please login to merge, or discard this patch.