Completed
Push — master ( 496d49...2a9f63 )
by
unknown
26:48
created
lib/private/legacy/OC_Helper.php 1 patch
Indentation   +373 added lines, -373 removed lines patch added patch discarded remove patch
@@ -32,380 +32,380 @@
 block discarded – undo
32 32
  * }
33 33
  */
34 34
 class OC_Helper {
35
-	private static ?ICacheFactory $cacheFactory = null;
36
-	private static ?bool $quotaIncludeExternalStorage = null;
37
-
38
-	/**
39
-	 * Recursive copying of folders
40
-	 * @param string $src source folder
41
-	 * @param string $dest target folder
42
-	 * @return void
43
-	 * @deprecated 32.0.0 - use \OCP\Files\Folder::copy
44
-	 */
45
-	public static function copyr($src, $dest) {
46
-		if (!file_exists($src)) {
47
-			return;
48
-		}
49
-
50
-		if (is_dir($src)) {
51
-			if (!is_dir($dest)) {
52
-				mkdir($dest);
53
-			}
54
-			$files = scandir($src);
55
-			foreach ($files as $file) {
56
-				if ($file != '.' && $file != '..') {
57
-					self::copyr("$src/$file", "$dest/$file");
58
-				}
59
-			}
60
-		} else {
61
-			$validator = \OCP\Server::get(FilenameValidator::class);
62
-			if (!$validator->isForbidden($src)) {
63
-				copy($src, $dest);
64
-			}
65
-		}
66
-	}
67
-
68
-	/**
69
-	 * detect if a given program is found in the search PATH
70
-	 *
71
-	 * @param string $name
72
-	 * @param bool $path
73
-	 * @internal param string $program name
74
-	 * @internal param string $optional search path, defaults to $PATH
75
-	 * @return bool true if executable program found in path
76
-	 * @deprecated 32.0.0 use the \OCP\IBinaryFinder
77
-	 */
78
-	public static function canExecute($name, $path = false) {
79
-		// path defaults to PATH from environment if not set
80
-		if ($path === false) {
81
-			$path = getenv('PATH');
82
-		}
83
-		// we look for an executable file of that name
84
-		$exts = [''];
85
-		$check_fn = 'is_executable';
86
-		// Default check will be done with $path directories :
87
-		$dirs = explode(PATH_SEPARATOR, (string)$path);
88
-		// WARNING : We have to check if open_basedir is enabled :
89
-		$obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir');
90
-		if ($obd != 'none') {
91
-			$obd_values = explode(PATH_SEPARATOR, $obd);
92
-			if (count($obd_values) > 0 && $obd_values[0]) {
93
-				// open_basedir is in effect !
94
-				// We need to check if the program is in one of these dirs :
95
-				$dirs = $obd_values;
96
-			}
97
-		}
98
-		foreach ($dirs as $dir) {
99
-			foreach ($exts as $ext) {
100
-				if ($check_fn("$dir/$name" . $ext)) {
101
-					return true;
102
-				}
103
-			}
104
-		}
105
-		return false;
106
-	}
107
-
108
-	/**
109
-	 * copy the contents of one stream to another
110
-	 *
111
-	 * @param resource $source
112
-	 * @param resource $target
113
-	 * @return array the number of bytes copied and result
114
-	 * @deprecated 5.0.0 - Use \OCP\Files::streamCopy
115
-	 */
116
-	public static function streamCopy($source, $target) {
117
-		return \OCP\Files::streamCopy($source, $target, true);
118
-	}
119
-
120
-	/**
121
-	 * Adds a suffix to the name in case the file exists
122
-	 *
123
-	 * @param string $path
124
-	 * @param string $filename
125
-	 * @return string
126
-	 */
127
-	public static function buildNotExistingFileName($path, $filename) {
128
-		$view = \OC\Files\Filesystem::getView();
129
-		return self::buildNotExistingFileNameForView($path, $filename, $view);
130
-	}
131
-
132
-	/**
133
-	 * Adds a suffix to the name in case the file exists
134
-	 *
135
-	 * @param string $path
136
-	 * @param string $filename
137
-	 * @return string
138
-	 */
139
-	public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
140
-		if ($path === '/') {
141
-			$path = '';
142
-		}
143
-		if ($pos = strrpos($filename, '.')) {
144
-			$name = substr($filename, 0, $pos);
145
-			$ext = substr($filename, $pos);
146
-		} else {
147
-			$name = $filename;
148
-			$ext = '';
149
-		}
150
-
151
-		$newpath = $path . '/' . $filename;
152
-		if ($view->file_exists($newpath)) {
153
-			if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
154
-				//Replace the last "(number)" with "(number+1)"
155
-				$last_match = count($matches[0]) - 1;
156
-				$counter = $matches[1][$last_match][0] + 1;
157
-				$offset = $matches[0][$last_match][1];
158
-				$match_length = strlen($matches[0][$last_match][0]);
159
-			} else {
160
-				$counter = 2;
161
-				$match_length = 0;
162
-				$offset = false;
163
-			}
164
-			do {
165
-				if ($offset) {
166
-					//Replace the last "(number)" with "(number+1)"
167
-					$newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
168
-				} else {
169
-					$newname = $name . ' (' . $counter . ')';
170
-				}
171
-				$newpath = $path . '/' . $newname . $ext;
172
-				$counter++;
173
-			} while ($view->file_exists($newpath));
174
-		}
175
-
176
-		return $newpath;
177
-	}
178
-
179
-	/**
180
-	 * Checks if a function is available
181
-	 *
182
-	 * @deprecated 25.0.0 use \OCP\Util::isFunctionEnabled instead
183
-	 */
184
-	public static function is_function_enabled(string $function_name): bool {
185
-		return Util::isFunctionEnabled($function_name);
186
-	}
187
-
188
-	/**
189
-	 * Try to find a program
190
-	 * @deprecated 25.0.0 Use \OCP\IBinaryFinder directly
191
-	 */
192
-	public static function findBinaryPath(string $program): ?string {
193
-		$result = Server::get(IBinaryFinder::class)->findBinaryPath($program);
194
-		return $result !== false ? $result : null;
195
-	}
196
-
197
-	/**
198
-	 * Calculate the disc space for the given path
199
-	 *
200
-	 * BEWARE: this requires that Util::setupFS() was called
201
-	 * already !
202
-	 *
203
-	 * @param string $path
204
-	 * @param \OCP\Files\FileInfo $rootInfo (optional)
205
-	 * @param bool $includeMountPoints whether to include mount points in the size calculation
206
-	 * @param bool $useCache whether to use the cached quota values
207
-	 * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct
208
-	 * @return StorageInfo
209
-	 * @throws \OCP\Files\NotFoundException
210
-	 */
211
-	public static function getStorageInfo($path, $rootInfo = null, $includeMountPoints = true, $useCache = true) {
212
-		if (!self::$cacheFactory) {
213
-			self::$cacheFactory = Server::get(ICacheFactory::class);
214
-		}
215
-		$memcache = self::$cacheFactory->createLocal('storage_info');
216
-
217
-		// return storage info without adding mount points
218
-		if (self::$quotaIncludeExternalStorage === null) {
219
-			self::$quotaIncludeExternalStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
220
-		}
221
-
222
-		$view = Filesystem::getView();
223
-		if (!$view) {
224
-			throw new \OCP\Files\NotFoundException();
225
-		}
226
-		$fullPath = Filesystem::normalizePath($view->getAbsolutePath($path));
227
-
228
-		$cacheKey = $fullPath . '::' . ($includeMountPoints ? 'include' : 'exclude');
229
-		if ($useCache) {
230
-			$cached = $memcache->get($cacheKey);
231
-			if ($cached) {
232
-				return $cached;
233
-			}
234
-		}
235
-
236
-		if (!$rootInfo) {
237
-			$rootInfo = \OC\Files\Filesystem::getFileInfo($path, self::$quotaIncludeExternalStorage ? 'ext' : false);
238
-		}
239
-		if (!$rootInfo instanceof \OCP\Files\FileInfo) {
240
-			throw new \OCP\Files\NotFoundException('The root directory of the user\'s files is missing');
241
-		}
242
-		$used = $rootInfo->getSize($includeMountPoints);
243
-		if ($used < 0) {
244
-			$used = 0.0;
245
-		}
246
-		/** @var int|float $quota */
247
-		$quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
248
-		$mount = $rootInfo->getMountPoint();
249
-		$storage = $mount->getStorage();
250
-		$sourceStorage = $storage;
251
-		if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
252
-			self::$quotaIncludeExternalStorage = false;
253
-		}
254
-		if (self::$quotaIncludeExternalStorage) {
255
-			if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
256
-				|| $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
257
-			) {
258
-				/** @var \OC\Files\Storage\Home $storage */
259
-				$user = $storage->getUser();
260
-			} else {
261
-				$user = \OC::$server->getUserSession()->getUser();
262
-			}
263
-			$quota = $user?->getQuotaBytes() ?? \OCP\Files\FileInfo::SPACE_UNKNOWN;
264
-			if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
265
-				// always get free space / total space from root + mount points
266
-				return self::getGlobalStorageInfo($quota, $user, $mount);
267
-			}
268
-		}
269
-
270
-		// TODO: need a better way to get total space from storage
271
-		if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
272
-			/** @var \OC\Files\Storage\Wrapper\Quota $storage */
273
-			$quota = $sourceStorage->getQuota();
274
-		}
275
-		try {
276
-			$free = $sourceStorage->free_space($rootInfo->getInternalPath());
277
-			if (is_bool($free)) {
278
-				$free = 0.0;
279
-			}
280
-		} catch (\Exception $e) {
281
-			if ($path === '') {
282
-				throw $e;
283
-			}
284
-			/** @var LoggerInterface $logger */
285
-			$logger = \OC::$server->get(LoggerInterface::class);
286
-			$logger->warning('Error while getting quota info, using root quota', ['exception' => $e]);
287
-			$rootInfo = self::getStorageInfo('');
288
-			$memcache->set($cacheKey, $rootInfo, 5 * 60);
289
-			return $rootInfo;
290
-		}
291
-		if ($free >= 0) {
292
-			$total = $free + $used;
293
-		} else {
294
-			$total = $free; //either unknown or unlimited
295
-		}
296
-		if ($total > 0) {
297
-			if ($quota > 0 && $total > $quota) {
298
-				$total = $quota;
299
-			}
300
-			// prevent division by zero or error codes (negative values)
301
-			$relative = round(($used / $total) * 10000) / 100;
302
-		} else {
303
-			$relative = 0;
304
-		}
305
-
306
-		/*
35
+    private static ?ICacheFactory $cacheFactory = null;
36
+    private static ?bool $quotaIncludeExternalStorage = null;
37
+
38
+    /**
39
+     * Recursive copying of folders
40
+     * @param string $src source folder
41
+     * @param string $dest target folder
42
+     * @return void
43
+     * @deprecated 32.0.0 - use \OCP\Files\Folder::copy
44
+     */
45
+    public static function copyr($src, $dest) {
46
+        if (!file_exists($src)) {
47
+            return;
48
+        }
49
+
50
+        if (is_dir($src)) {
51
+            if (!is_dir($dest)) {
52
+                mkdir($dest);
53
+            }
54
+            $files = scandir($src);
55
+            foreach ($files as $file) {
56
+                if ($file != '.' && $file != '..') {
57
+                    self::copyr("$src/$file", "$dest/$file");
58
+                }
59
+            }
60
+        } else {
61
+            $validator = \OCP\Server::get(FilenameValidator::class);
62
+            if (!$validator->isForbidden($src)) {
63
+                copy($src, $dest);
64
+            }
65
+        }
66
+    }
67
+
68
+    /**
69
+     * detect if a given program is found in the search PATH
70
+     *
71
+     * @param string $name
72
+     * @param bool $path
73
+     * @internal param string $program name
74
+     * @internal param string $optional search path, defaults to $PATH
75
+     * @return bool true if executable program found in path
76
+     * @deprecated 32.0.0 use the \OCP\IBinaryFinder
77
+     */
78
+    public static function canExecute($name, $path = false) {
79
+        // path defaults to PATH from environment if not set
80
+        if ($path === false) {
81
+            $path = getenv('PATH');
82
+        }
83
+        // we look for an executable file of that name
84
+        $exts = [''];
85
+        $check_fn = 'is_executable';
86
+        // Default check will be done with $path directories :
87
+        $dirs = explode(PATH_SEPARATOR, (string)$path);
88
+        // WARNING : We have to check if open_basedir is enabled :
89
+        $obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir');
90
+        if ($obd != 'none') {
91
+            $obd_values = explode(PATH_SEPARATOR, $obd);
92
+            if (count($obd_values) > 0 && $obd_values[0]) {
93
+                // open_basedir is in effect !
94
+                // We need to check if the program is in one of these dirs :
95
+                $dirs = $obd_values;
96
+            }
97
+        }
98
+        foreach ($dirs as $dir) {
99
+            foreach ($exts as $ext) {
100
+                if ($check_fn("$dir/$name" . $ext)) {
101
+                    return true;
102
+                }
103
+            }
104
+        }
105
+        return false;
106
+    }
107
+
108
+    /**
109
+     * copy the contents of one stream to another
110
+     *
111
+     * @param resource $source
112
+     * @param resource $target
113
+     * @return array the number of bytes copied and result
114
+     * @deprecated 5.0.0 - Use \OCP\Files::streamCopy
115
+     */
116
+    public static function streamCopy($source, $target) {
117
+        return \OCP\Files::streamCopy($source, $target, true);
118
+    }
119
+
120
+    /**
121
+     * Adds a suffix to the name in case the file exists
122
+     *
123
+     * @param string $path
124
+     * @param string $filename
125
+     * @return string
126
+     */
127
+    public static function buildNotExistingFileName($path, $filename) {
128
+        $view = \OC\Files\Filesystem::getView();
129
+        return self::buildNotExistingFileNameForView($path, $filename, $view);
130
+    }
131
+
132
+    /**
133
+     * Adds a suffix to the name in case the file exists
134
+     *
135
+     * @param string $path
136
+     * @param string $filename
137
+     * @return string
138
+     */
139
+    public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) {
140
+        if ($path === '/') {
141
+            $path = '';
142
+        }
143
+        if ($pos = strrpos($filename, '.')) {
144
+            $name = substr($filename, 0, $pos);
145
+            $ext = substr($filename, $pos);
146
+        } else {
147
+            $name = $filename;
148
+            $ext = '';
149
+        }
150
+
151
+        $newpath = $path . '/' . $filename;
152
+        if ($view->file_exists($newpath)) {
153
+            if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) {
154
+                //Replace the last "(number)" with "(number+1)"
155
+                $last_match = count($matches[0]) - 1;
156
+                $counter = $matches[1][$last_match][0] + 1;
157
+                $offset = $matches[0][$last_match][1];
158
+                $match_length = strlen($matches[0][$last_match][0]);
159
+            } else {
160
+                $counter = 2;
161
+                $match_length = 0;
162
+                $offset = false;
163
+            }
164
+            do {
165
+                if ($offset) {
166
+                    //Replace the last "(number)" with "(number+1)"
167
+                    $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length);
168
+                } else {
169
+                    $newname = $name . ' (' . $counter . ')';
170
+                }
171
+                $newpath = $path . '/' . $newname . $ext;
172
+                $counter++;
173
+            } while ($view->file_exists($newpath));
174
+        }
175
+
176
+        return $newpath;
177
+    }
178
+
179
+    /**
180
+     * Checks if a function is available
181
+     *
182
+     * @deprecated 25.0.0 use \OCP\Util::isFunctionEnabled instead
183
+     */
184
+    public static function is_function_enabled(string $function_name): bool {
185
+        return Util::isFunctionEnabled($function_name);
186
+    }
187
+
188
+    /**
189
+     * Try to find a program
190
+     * @deprecated 25.0.0 Use \OCP\IBinaryFinder directly
191
+     */
192
+    public static function findBinaryPath(string $program): ?string {
193
+        $result = Server::get(IBinaryFinder::class)->findBinaryPath($program);
194
+        return $result !== false ? $result : null;
195
+    }
196
+
197
+    /**
198
+     * Calculate the disc space for the given path
199
+     *
200
+     * BEWARE: this requires that Util::setupFS() was called
201
+     * already !
202
+     *
203
+     * @param string $path
204
+     * @param \OCP\Files\FileInfo $rootInfo (optional)
205
+     * @param bool $includeMountPoints whether to include mount points in the size calculation
206
+     * @param bool $useCache whether to use the cached quota values
207
+     * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct
208
+     * @return StorageInfo
209
+     * @throws \OCP\Files\NotFoundException
210
+     */
211
+    public static function getStorageInfo($path, $rootInfo = null, $includeMountPoints = true, $useCache = true) {
212
+        if (!self::$cacheFactory) {
213
+            self::$cacheFactory = Server::get(ICacheFactory::class);
214
+        }
215
+        $memcache = self::$cacheFactory->createLocal('storage_info');
216
+
217
+        // return storage info without adding mount points
218
+        if (self::$quotaIncludeExternalStorage === null) {
219
+            self::$quotaIncludeExternalStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false);
220
+        }
221
+
222
+        $view = Filesystem::getView();
223
+        if (!$view) {
224
+            throw new \OCP\Files\NotFoundException();
225
+        }
226
+        $fullPath = Filesystem::normalizePath($view->getAbsolutePath($path));
227
+
228
+        $cacheKey = $fullPath . '::' . ($includeMountPoints ? 'include' : 'exclude');
229
+        if ($useCache) {
230
+            $cached = $memcache->get($cacheKey);
231
+            if ($cached) {
232
+                return $cached;
233
+            }
234
+        }
235
+
236
+        if (!$rootInfo) {
237
+            $rootInfo = \OC\Files\Filesystem::getFileInfo($path, self::$quotaIncludeExternalStorage ? 'ext' : false);
238
+        }
239
+        if (!$rootInfo instanceof \OCP\Files\FileInfo) {
240
+            throw new \OCP\Files\NotFoundException('The root directory of the user\'s files is missing');
241
+        }
242
+        $used = $rootInfo->getSize($includeMountPoints);
243
+        if ($used < 0) {
244
+            $used = 0.0;
245
+        }
246
+        /** @var int|float $quota */
247
+        $quota = \OCP\Files\FileInfo::SPACE_UNLIMITED;
248
+        $mount = $rootInfo->getMountPoint();
249
+        $storage = $mount->getStorage();
250
+        $sourceStorage = $storage;
251
+        if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
252
+            self::$quotaIncludeExternalStorage = false;
253
+        }
254
+        if (self::$quotaIncludeExternalStorage) {
255
+            if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
256
+                || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
257
+            ) {
258
+                /** @var \OC\Files\Storage\Home $storage */
259
+                $user = $storage->getUser();
260
+            } else {
261
+                $user = \OC::$server->getUserSession()->getUser();
262
+            }
263
+            $quota = $user?->getQuotaBytes() ?? \OCP\Files\FileInfo::SPACE_UNKNOWN;
264
+            if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
265
+                // always get free space / total space from root + mount points
266
+                return self::getGlobalStorageInfo($quota, $user, $mount);
267
+            }
268
+        }
269
+
270
+        // TODO: need a better way to get total space from storage
271
+        if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) {
272
+            /** @var \OC\Files\Storage\Wrapper\Quota $storage */
273
+            $quota = $sourceStorage->getQuota();
274
+        }
275
+        try {
276
+            $free = $sourceStorage->free_space($rootInfo->getInternalPath());
277
+            if (is_bool($free)) {
278
+                $free = 0.0;
279
+            }
280
+        } catch (\Exception $e) {
281
+            if ($path === '') {
282
+                throw $e;
283
+            }
284
+            /** @var LoggerInterface $logger */
285
+            $logger = \OC::$server->get(LoggerInterface::class);
286
+            $logger->warning('Error while getting quota info, using root quota', ['exception' => $e]);
287
+            $rootInfo = self::getStorageInfo('');
288
+            $memcache->set($cacheKey, $rootInfo, 5 * 60);
289
+            return $rootInfo;
290
+        }
291
+        if ($free >= 0) {
292
+            $total = $free + $used;
293
+        } else {
294
+            $total = $free; //either unknown or unlimited
295
+        }
296
+        if ($total > 0) {
297
+            if ($quota > 0 && $total > $quota) {
298
+                $total = $quota;
299
+            }
300
+            // prevent division by zero or error codes (negative values)
301
+            $relative = round(($used / $total) * 10000) / 100;
302
+        } else {
303
+            $relative = 0;
304
+        }
305
+
306
+        /*
307 307
 		 * \OCA\Files_Sharing\External\Storage returns the cloud ID as the owner for the storage.
308 308
 		 * It is unnecessary to query the user manager for the display name, as it won't have this information.
309 309
 		 */
310
-		$isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class);
311
-
312
-		$ownerId = $storage->getOwner($path);
313
-		$ownerDisplayName = '';
314
-
315
-		if ($isRemoteShare === false && $ownerId !== false) {
316
-			$ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? '';
317
-		}
318
-
319
-		if (substr_count($mount->getMountPoint(), '/') < 3) {
320
-			$mountPoint = '';
321
-		} else {
322
-			[,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4);
323
-		}
324
-
325
-		$info = [
326
-			'free' => $free,
327
-			'used' => $used,
328
-			'quota' => $quota,
329
-			'total' => $total,
330
-			'relative' => $relative,
331
-			'owner' => $ownerId,
332
-			'ownerDisplayName' => $ownerDisplayName,
333
-			'mountType' => $mount->getMountType(),
334
-			'mountPoint' => trim($mountPoint, '/'),
335
-		];
336
-
337
-		if ($isRemoteShare === false && $ownerId !== false && $path === '/') {
338
-			// If path is root, store this as last known quota usage for this user
339
-			\OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative);
340
-		}
341
-
342
-		$memcache->set($cacheKey, $info, 5 * 60);
343
-
344
-		return $info;
345
-	}
346
-
347
-	/**
348
-	 * Get storage info including all mount points and quota
349
-	 *
350
-	 * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct
351
-	 * @return StorageInfo
352
-	 */
353
-	private static function getGlobalStorageInfo(int|float $quota, IUser $user, IMountPoint $mount): array {
354
-		$rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
355
-		/** @var int|float $used */
356
-		$used = $rootInfo['size'];
357
-		if ($used < 0) {
358
-			$used = 0.0;
359
-		}
360
-
361
-		$total = $quota;
362
-		/** @var int|float $free */
363
-		$free = $quota - $used;
364
-
365
-		if ($total > 0) {
366
-			if ($quota > 0 && $total > $quota) {
367
-				$total = $quota;
368
-			}
369
-			// prevent division by zero or error codes (negative values)
370
-			$relative = round(($used / $total) * 10000) / 100;
371
-		} else {
372
-			$relative = 0.0;
373
-		}
374
-
375
-		if (substr_count($mount->getMountPoint(), '/') < 3) {
376
-			$mountPoint = '';
377
-		} else {
378
-			[,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4);
379
-		}
380
-
381
-		return [
382
-			'free' => $free,
383
-			'used' => $used,
384
-			'total' => $total,
385
-			'relative' => $relative,
386
-			'quota' => $quota,
387
-			'owner' => $user->getUID(),
388
-			'ownerDisplayName' => $user->getDisplayName(),
389
-			'mountType' => $mount->getMountType(),
390
-			'mountPoint' => trim($mountPoint, '/'),
391
-		];
392
-	}
393
-
394
-	public static function clearStorageInfo(string $absolutePath): void {
395
-		/** @var ICacheFactory $cacheFactory */
396
-		$cacheFactory = \OC::$server->get(ICacheFactory::class);
397
-		$memcache = $cacheFactory->createLocal('storage_info');
398
-		$cacheKeyPrefix = Filesystem::normalizePath($absolutePath) . '::';
399
-		$memcache->remove($cacheKeyPrefix . 'include');
400
-		$memcache->remove($cacheKeyPrefix . 'exclude');
401
-	}
402
-
403
-	/**
404
-	 * Returns whether the config file is set manually to read-only
405
-	 * @return bool
406
-	 * @deprecated 32.0.0 use the `config_is_read_only` system config directly
407
-	 */
408
-	public static function isReadOnlyConfigEnabled() {
409
-		return \OC::$server->getConfig()->getSystemValueBool('config_is_read_only', false);
410
-	}
310
+        $isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class);
311
+
312
+        $ownerId = $storage->getOwner($path);
313
+        $ownerDisplayName = '';
314
+
315
+        if ($isRemoteShare === false && $ownerId !== false) {
316
+            $ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? '';
317
+        }
318
+
319
+        if (substr_count($mount->getMountPoint(), '/') < 3) {
320
+            $mountPoint = '';
321
+        } else {
322
+            [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4);
323
+        }
324
+
325
+        $info = [
326
+            'free' => $free,
327
+            'used' => $used,
328
+            'quota' => $quota,
329
+            'total' => $total,
330
+            'relative' => $relative,
331
+            'owner' => $ownerId,
332
+            'ownerDisplayName' => $ownerDisplayName,
333
+            'mountType' => $mount->getMountType(),
334
+            'mountPoint' => trim($mountPoint, '/'),
335
+        ];
336
+
337
+        if ($isRemoteShare === false && $ownerId !== false && $path === '/') {
338
+            // If path is root, store this as last known quota usage for this user
339
+            \OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative);
340
+        }
341
+
342
+        $memcache->set($cacheKey, $info, 5 * 60);
343
+
344
+        return $info;
345
+    }
346
+
347
+    /**
348
+     * Get storage info including all mount points and quota
349
+     *
350
+     * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct
351
+     * @return StorageInfo
352
+     */
353
+    private static function getGlobalStorageInfo(int|float $quota, IUser $user, IMountPoint $mount): array {
354
+        $rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext');
355
+        /** @var int|float $used */
356
+        $used = $rootInfo['size'];
357
+        if ($used < 0) {
358
+            $used = 0.0;
359
+        }
360
+
361
+        $total = $quota;
362
+        /** @var int|float $free */
363
+        $free = $quota - $used;
364
+
365
+        if ($total > 0) {
366
+            if ($quota > 0 && $total > $quota) {
367
+                $total = $quota;
368
+            }
369
+            // prevent division by zero or error codes (negative values)
370
+            $relative = round(($used / $total) * 10000) / 100;
371
+        } else {
372
+            $relative = 0.0;
373
+        }
374
+
375
+        if (substr_count($mount->getMountPoint(), '/') < 3) {
376
+            $mountPoint = '';
377
+        } else {
378
+            [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4);
379
+        }
380
+
381
+        return [
382
+            'free' => $free,
383
+            'used' => $used,
384
+            'total' => $total,
385
+            'relative' => $relative,
386
+            'quota' => $quota,
387
+            'owner' => $user->getUID(),
388
+            'ownerDisplayName' => $user->getDisplayName(),
389
+            'mountType' => $mount->getMountType(),
390
+            'mountPoint' => trim($mountPoint, '/'),
391
+        ];
392
+    }
393
+
394
+    public static function clearStorageInfo(string $absolutePath): void {
395
+        /** @var ICacheFactory $cacheFactory */
396
+        $cacheFactory = \OC::$server->get(ICacheFactory::class);
397
+        $memcache = $cacheFactory->createLocal('storage_info');
398
+        $cacheKeyPrefix = Filesystem::normalizePath($absolutePath) . '::';
399
+        $memcache->remove($cacheKeyPrefix . 'include');
400
+        $memcache->remove($cacheKeyPrefix . 'exclude');
401
+    }
402
+
403
+    /**
404
+     * Returns whether the config file is set manually to read-only
405
+     * @return bool
406
+     * @deprecated 32.0.0 use the `config_is_read_only` system config directly
407
+     */
408
+    public static function isReadOnlyConfigEnabled() {
409
+        return \OC::$server->getConfig()->getSystemValueBool('config_is_read_only', false);
410
+    }
411 411
 }
Please login to merge, or discard this patch.